Skip to main content

Full text of "From the ground up: logic gates et al."

See other formats


w 



from the ground up 



logic gates et al. 



Daniele Giacomini appunti2@gmail.com 



draft-20 13.03 




0 



'1 ' 
1 1 



Y y ... y ... ... ... ... ... 

o o r u 1 

' 1 ' / '''II'' 

I I \) I I I I I I 

I I I I - I I I I I 

I I \l I I I I f~J 

it i 4- / / / / I I 

I I I I I I 

/ / / ' 1 ' ' 

/ / / _L / i -t 
i 1 i i i i i 
|_ / / I / / / 



0 



/ 



1 



/ / 



0 



/ I I I I I 

I 1111/ 



1 



/ / 
/ / 



0 i J 0 n 

1i / / / ' \ji 

li- / I I I 

111,11 1 I 

1 ' 'VJ 



/ i i i i i 

/ / X / 

/ / / / 



0 A 

U / / 
y ' 1 U 

/ / / 

0 



GNU „„ T GNU T CC 

GPL FDL BY-SA 



"from the ground up" -- Copyright © 2013 Daniele Giacomini 

Via Morganella Est, 21 — 1-31050 Ponzano Veneto (TV) — appunti2@gmail.com 

You can redistribute this work and/or modify it under the terms of the GNU General Public License 
as published by the Free Software Foundation; either version 3 of the License, or (at your option) any 
later version, with the following exceptions and clarifications: 

• Quotations and samples of other works are not subject to the scope of the license of this work. 

• If you modify this work and/or reuse it partially, under the terms of the license: it is your responsi- 
bility to avoid misrepresentation of opinion, thought and/or feeling of other than you; the notices 
about changes and the references about the original work, must be kept and evidenced conforming 
to the new work characteristics; you may add or remove quotations and/or samples of other works; 
you are required to use a different name for the new work. 

Permission is also granted to copy, distribute and/or modify this work under the terms of the GNU Free 
Documentation License (FDL), either version 1.3 of the License, or (at your option) any later version 
published by the Free Software Foundation (FSF); with no Invariant Sections, with no Front-Cover 
Text, and with no Back-Cover Texts. 

Permission is also granted to copy, distribute and/or modify this work under the terms of the Creative 
Commons Attribution-Share Alike License, version 3.0, as published by Creative Commons at http:// 
creativecommons.org/licenses/by-sa/3. 0/ . 

This work is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 



II 



Table of contents 

Foreword IV 

Part i Logic circuits 1 

Traditional logic integrated circuits 243 

References 301 

Part ii Simple CPU 303 

References 981 

Index i 



III 



Foreword 

Dear reader, this work is almost a collection of notes on the fields I like to study. I 
do it using English because this is the language for the information technology when 
the concepts are beyond the common interest and because I would like to practice 
with English as well. As you can understand from these few lines, I might be a good 
English reader, but surely I am not a good writer. If you are interested on the topic of 
this book and you will read it, please be prepared and please forgive me, but if you 
are connected and you like it to do, I would appreciate if you send me a note about the 
phrases that I might correct (it is enough that you write something like: "you wrote 
this... but you should write that..."). My email address is appunti2@gmail.com. 

Who am I? I was a technical teacher at high school. I was excited in 1981 when I 
could use a Burroughs B91: I learned to write COBOL programs and experienced 
with other Burroughs proprietary languages for the system maintenance. Then, I felt 
excited again in 1995 when I started studying GNU/Linux systems and I dreamed 
(again) a world of free software, free knowledge (and peaceful living); I also wrote 
a free book about GNU/Linux and what it can be done with it (of course, I used my 
mother language for it). But I found that things do not work as simple as in my dream 
— especially with my teaching experience — because in human nature the 'freedom' is 
something that is not appreciated if it is 'free'. Freedom is not just a matter of money 
or laws, but when it should be applied to the information technology the freedom 
requires knowledge: information technology is something on what we all depend for 
our life, but depending on what we can not verify — because we do not understand in- 
depth or because, for unknown reasons, we prefer what is not open source — we will 
be just slave. Anyway, although my thoughts are so catastrophic, I am still attracted 
from what I felt in my young ages, when I imagined that computers could be built 
simply with discrete logic (and all the software could be written from scratch)... :-) 

Daniele Giacomini 
Via Morganella Est, 21 
1-31050 Ponzano Veneto (TV) 
Italy 

appunti2 @ gmail.com 

h ttp ://it. linkedin . com/pub/daniele-giacomini/4b/3 64/6b2 
http://informaticalibera.net 



IV 



Part i 

Logic circuits 



Logic functions and logic gates 5 

1.1 NOT 7 

1.2 'not-inverter' or 'buffer' 7 

1.3 AND 8 

1.4 OR 9 

1.5 XOR 9 

1.6 Logic networks 10 

1.7 Operator precedence 13 

1.8 Irrelevant values inside the truth table 13 

1.9 Equivalence 13 

1.10 Sum of produtcs 17 

1.11 Karnaugh maps 19 

1.12 Logic gates and multiple lines 24 

1.13 Electronic logic gates 25 

1.14 HDL 28 

Introduction to Verilog 31 

2.1 Minimal notions 33 

2.2 Hello world! 33 

2.3 Compiler directives 38 

2.4 Signal values 41 

2.5 Literal constants 41 

2.6 Data types 43 

2.7 Ports 46 

2.8 Parameters 48 

2.9 Module declarations 48 

2.10 Module instance 51 



1 



2.11 Fully qualified path names 51 

2.12 Primitives 52 

2.13 Expressions 54 

2.14 Vector and array addressing 58 

2.15 Strings 59 

2.16 Functions 60 

2.17 Netlist modules: combinational circuits 62 

2.18 Behavioral modules 68 

2.19 Procedural assignments 69 

2.20 Blocking delays 71 

2.21 Wait for a level event 72 

2.22 Wait for an event expressions 74 

2.23 Event variables 76 

2.24 System tasks and functions 76 

2.25 Control structures 78 

2.26 Thread control 81 

3 Combinational circuits 83 

3.1 Decoder 87 

3.2 Demultiplexer 90 

3.3 Multiplexer 93 

3.4 Multiplexer and demultiplexer with paralel I/O 96 

3.5 Binary encoder 99 

3.6 Priority encoder 102 

3.7 Logic units 106 

3.8 Shift and rotation 107 

3.9 Addition 114 

3.10 Subtraction 119 

3.11 Addition and subtraction together 123 

3.12 Carry lookahead 125 

3.13 2's complement 132 

2 



3.14 Multiplication 133 

3.15 Division 142 

3.16 Magnitude comparator 145 

4 Arithmetic-logic unit 149 

4.1 Status flags 150 

4.2 Size truncation 152 

4.3 Sign inversion 154 

4.4 Addition and subtraction 156 

4.5 Shift and rotation 158 

4.6 Magnitude comparation 162 

4.7 Multiplication 165 

4.8 Division 171 

4.9 Logic unit 176 

4.10 Joining all the module together 177 

4.11 Bit sliced ALU 179 

5 Latch and flip-flop 185 

5.1 Propagation delay 185 

5.2 Truth tables 187 

5.3 SR latch 188 

5.4 Bounce-free switch 193 

5.5 Gated SR latches 193 

5.6 SR flip-flop 195 

5.7 Time: setup/hold and recovery/removal 198 

5.8 D latch and D flip-flop 199 

5.9 T flip-flop 203 

5.10 JK flip-flop 204 

5.11 Troublesome JK flip-flops 207 

6 Registers 211 

6.1 Simple data register 212 

3 



6.2 Shift register 216 

6.3 Asynchronous counter with T flip-flop 217 

6.4 Synchronous T flip-flop counters 219 

6.5 Synchronous counters with D flip-flops 220 

6.6 Synchronous counters with paralel load 224 

7 Bus and control unit 229 

7.1 Tri-state buffer 229 

7.2 Hardcoded bus control unit 232 

7.3 Microcode 236 

Traditional logic integrated circuits 243 

Data distributors or demultiplexers 244 

Data selectors or multiplexers 257 

Special circuits 271 

Arithmetic units 275 

References 301 



4 



Chapter 

Logic functions and logic gates 



1.1 not 7 

1.2 'not-inverter' or 'buffer' 7 

1.3 AND 8 

1.4 OR 9 

1.5 XOR 9 

1.6 Logic networks 10 

1.7 Operator precedence 13 

1.8 Irrelevant values inside the truth table 13 

1.9 Equivalence 13 

1.10 Sum of produtcs 17 

1.11 Karnaugh maps 19 

1.12 Logic gates and multiple lines 24 

1.13 Electronic logic gates 25 

1.14 HDL 28 



active high 10 active low 10 AND 8 assert 10 boolean algebra 13 buffer 7 De 
Morgan's laws 13 discrete logic 25 floating 25 fundamental product 17 hardware 
description language 28 HDL 28 high impedance 25 IC 25 integrated circuit 25 
inverter 7 Karnaugh map 19 logic circuit 10 logic connective 5 logic gate 5 logic 
network 10 logic operator 5 logic variable 5 negate 10 NOT 7 not-inverter 7 OR 9 
propagation delay 25 signal 10 sum of products 17 tri-state buffer 25 Verilog 28 
XOR 9 Z 25 

The term logic comes from the philosophy and it is the way by which something can 
be found true or false. The concepts of 'true' and 'false' can be considered as the two 
elementary values of a logic variable. There are different ways to represent the values 
of a logic variable and every context might have its own symbology, but when using 



6 



Logic functions and logic gates 



numbers — unless otherwise specified — it is custom to associate 1 to 'true' and 0 to 
'false'. 

A logic expression, or a logic function, is the expression or the function that produces 
a true or false result. The components of a logic expression or function are listed 
below: 

• declarative propositions - propositions that can be found either true or false; 

• logic constants - either true or false; 

• logic variables - variables that can represent only the values true and false; 

• logic functions and operators - the functions or the operators used to connect the 
other logic components into a more complex function or expression. 

Logical functions can be represented in different ways, depending on the context and 
on possible typographical limitations. Therefore, every time it is necessary to under- 
stand which is the adopted symbology, taking into account that the representation 
might change inside the same document; for example, the body text explaining a 
problem might use one symbology, whereas the pictures might have a different and 
more appropriate one. One particular way to represent a logic function consists on 
drawing little boxes, with one or more inputs and one single output: these are known 
as logic gates. 

Table 1.1. Some alternative notations regarding the common logic functions, as- 
sociating the symbology used for the corresponding logic gates. 



® 


a 


a — 


^> a 


© 


not a 


a' -ia 


a 


a — 


a 


(aQb) 


a and b 


a a b 


a-b 


ab 


a — 
b — 


Jr~ a-b 


(aTb) 


a or b 


a vb 


a + b 


a — 
b - 


D- a+b 


(aQb) 


a xor b 


a © b 


a 


) aeb 



Logic functions and logic gates 



7 



The truth tables are used to define the meaning of logic operators: all the values of 
the input variables are matched with the corresponding logic results. 

1.1 NOT 

The NOT function has a single input and produces the logic inversion. That is: if the 
input is true (1), the output is false (0) and vice versa. When the NOT function is 
represented in the form of a logic gate, it is known with the name inverter. 

Figure 1.2. NOT (inverter). 



input 


output 


a 


a 


0 


1 


1 


0 



input 




output 



a 



input 



a 



o 




output 



a 



inverter 



inverter 



truth table 

The figure above shows that there are two alternative way to represent an inverter 
gate: the first one is the most common. 

1.2 x not-inverter' or 'buffer' 

Two consecutive inversions give just the original logic value; that is, "NOT (NOT 
A)" is just the same as "A". There is a logic gate that is known as not-inverter or 
buffer: it does nothing from the logic point of view, but it has some meaning for other 
problems. 

Figure 1.3. Buffer (not-inverter). 

input output input 



a 


a 


0 


0 


1 


1 




input 

a 





o 




output 

a 



« 



« 



truth table 



not-inverter 



8 



Logic functions and logic gates 



From the example shown for the inverter and the buffer logic gates, it should be 
noticed the use of the little bubble that means logic inversion. This bubble can 
appear at the input or at the output and it might be used also with other logic gates. 



« 



1.3 AND 

The AND function takes two inputs and the result is true only if both inputs are true, 
otherwise the result is false. 

Figure 1.4. AND. 

input output 



a 


b 


a • b 


0 


0 


0 


0 


1 


0 


1 


0 


0 


1 


1 


1 



input 

a 
b 




output 



a • b 



truth table 

The AND logic function might have more than two input variables and the result is 
true only if all the inputs are also true. The same way, the AND logic gate might have 
more than two input lines, as it is shown in the following figure. 

Figure 1.5. AND gate with more than two inputs. 



a 
b 



a-b- 



z 



Logic functions and logic gates 9 
1.4 OR 

The OR logic function takes two inputs and the result is true if at least one input is 
true, otherwise the result is false. 



« 



1.6. OR. 




input 


output 


a b 


t 

a + b 


0 0 


0 


0 1 


1 


1 0 


1 


1 1 


1 



input 

a 




output 



a + b 



truth table 

The OR logic function might have more than two input variables and the result is true 
if at least one input is also true. The same way, the OR logic gate might have more 
than two input lines, as it is shown in the following figure. 

Figure 1.7. OR gate with more than two inputs. 

a 
b 




a+b+ ... +z 



1.5 XOR 

The XOR logic function (exclusive or) is derived from the other one: it takes two 
inputs and the result is true if only one input is true, otherwise the result is false. 



« 



10 



Logic functions and logic gates 



Figure 1.8. XOR. 



input 



output 



a 


b 


a0b 


n 
U 


0 


0 


0 


1 


1 


1 


0 


1 


1 


1 


0 




truth table 



input 




output 



aeb 



Even the XOR logic function might have more than two input variables and the result 
is true if only one input is also true. The same way, the XOR logic gate might have 
more than two input lines, as it is shown in the following figure. 

Figure 1.9. XOR gate with more than two inputs. 



a 
b 




a©b©...©z 



« 



1 .6 Logic networks 

Elementary logic functions can be used together to build more complex ones. When 
using logic gates, connecting two or more gates results into a logic network or logic 
circuit, which are equivalent definitions of the same thing. 



Logic functions and logic gates 



11 



Figure 1.10. A simple logic network. 

logic network 



W 



X 



X 



w 



> 



/ 



X 

1 


X 

2 


f( x v x i) 


0 


0 


0 


0 


1 


0 


1 


0 


1 


1 


1 


0 



truth table 



logic function 

The logic gates are connected together with wires; the figure above shows a name for 
every wire, where jti and X2 are the inputs of the overall logic function and / is the 
output. Each wire can carry a value of 0 or 1 that in electronics is represented by a 
tension (measured in Volts and known also as voltage). In electronic circuits there is 
usually a common connection known as ground, because it carries the 0-volt point of 
reference for the other electric tensions. In a logic circuit, when a wire has the same 
voltage of the ground, it represents the value 0; when the electric tension is higher (or 
lower, depending on the specific technology used) the value that a wire represents is 
1. 

Together with the truth table, a logic network might have also a timing diagram, where 
the electric signals (the tensions) are shown dynamically, like the example below: 
when the line of the diagram is low it represents the value 0; when the line is high it 
represents the value 1 . 



12 



Logic functions and logic gates 



x 



X 



w 



f 



Figure 1.11. Timing diagram. 
1 

0 

1 



0 

1 

0 

1 

0 

1 

0 



time 



The electric signal (tension) used to represent the value 1 might be positive or negative 
in relation to the ground potential. The choice to be positive or negative depends on 
the technology used to build the logic gates. When a timing diagram is drawn, the 
value of the signal used to represent 1 is always shown high, regardless if it is a 
positive or negative tension. 

Figure 1.12. The simple logic network with a negated wire name. 

W 

X 



X 



> 



X 



When a wire is named, this name might be negated. The figure above shows the same 
simple logic network, where the previous wire w 2 is replaced by the name x 2 . In fact, 
the wire x 2 is obtained inverting the value at the wire x 2 and so it is easier to read the 
logic network. 

It is common to use the word 'active' to mean 1 on a wire, but when a wire is labeled 
with a negated name, the meaning of 'active' becomes ambiguous. The name of the 
wire implies the name of the signal it carries: a plain name (without negation) means 
that this is the name of the high signal or the name of the value 1 (active high); on 



Logic functions and logic gates 



13 



the other hand, a negated name is the name of a low signal or the name of a value 0 
(active low). To express the meaning that the signal is the one that it is expected to 
be, based on the name of the wire, it is custom to use the words assert and negate. 
For example, in the above figure, the wire W\ is asserted when it is high — or one — 
and negated when it is low — or zero — , whereas the wire x~2 is asserted when it is low 
— or zero — and it is negated when it is high — or one — . 

1 .7 Operator precedence 



When the logic functions are written in the form of expressions, it is important to 
define the order of precedence, to avoid an excessive use of parentheses. This order is: 
NOT, AND, OR. For example, a+b c means exactly a+(b-(c)). It should be noticed 
that it works like the usual arithmetic, where multiplication has the precedence on the 
addition. 

The precedence problem is not related to logic networks, because the connections 
define the order of evaluation. 

It is not specified the precedence order for the XOR operator, because it is a derived 
function of the other ones. So, if ambiguity might occur with a logic expression, 
parentheses should be used. 



1 .8 Irrelevant values inside the truth table 



There are situation where truth tables of logic functions can be reduced, because for 
some conditions the value of some inputs are irrelevant. When an input value might be 
anything, it is used a letter 'X' . For example, the simple function shown on a previous 
section is (xi+X2)-X2 and it happens that if Xi is 0, it does not matter what value has 
X2, because the output remains 0. 

Figure 1.13. Truth table simplified. 



« 



« 



x 



x 



2 



f( x v x 2 ) 



f( x x > x 2 ) 



X 



X 



0 
0 
1 
1 



0 
1 
0 
1 



0 
0 
1 
0 



2 



f= (X + X ) . X 

J v 1 1' 2 




0 X 

1 0 
1 1 



0 
1 
0 



14 



Logic functions and logic gates 



1.9 Equivalence 

« 

Through the elementary logic operators it is possible to build complex functions, 
where there are different alternatives to obtain the same result. For example, the XOR 
function might be obtained as (a+b)-(a+b) or as (a+b)(ab) or as (a+b) (a+b), or 
even more complex and less useful ways. To transform a logic function into another, 
producing the same result, come to help the De Morgan's laws: 

a • Z>= {a+b) 



a+b= (a-b) 



Putting together the truth tables of the basic logic functions with the De Morgan's 
laws, it is possible to find the equivalences shown in the following table; equivalences 
on which is based all the 'logic' algebra, better known as the boolean algebra (or 
Boole's algebra). 

Table 1.15. Boolean algebra equivalences. 



(1) 


a+0 = a 


(2) 


a-0 = 0 


(3) 


a+1 = 1 


(4) 


a-l = a 


(5) 


a+a = a 


(6) 


aa = a 


(7) 


a+a = 1 


(8) 


a a = 0 


(9) 


a+b - b+a 


(10) 


ab - ba 


(11) 


a+(b+c) = (a+b)+c 


(12) 


a (b e) = (a b) c 


(13) 


a(b+c) = ab+ac 


(14) 


a+bc = (a+b)-(a+c) 


(15) 


{a+b) - a b 


(16) 


(a b) - a+b 


(17) 


(a) = a 







1. a+0 = a 




b 



a-b = 



a 
b 



(a+b) 



a 



— o 

-Q 



a+b 



a 
b 



(a-b) 



Logic functions and logic gates 



15 



2. a-0 = 0 

a 
0 

3. a+l = 1 

a 
1 



= i 



4. fl l = fl 

a _ 
1 " 



> 1 



5. a +a = a 

a_ 
a - 



a 



6. a a = a 

a_ 
a~ 



> 



a 



7. a+a = 1 

a - 



8. a a = 0 



J-o 



9. a+b = b+a 

a 



a+b 



10. a b = b a 

a 

b 



; — a-b 



11. a+(b+c) = (a+b)+c 



a 



b. 
a 

b 

a 



a 

b 

c 



a+(b+c) 



t5 



-o 



J-o 



b+a 



J-b- 



a 



12. a (b e) = (a b) c 



a 

b 

c 



a-(b-c) 



b 

c 



a 
b 
c 



(a+b)+c 



1_ 



(a-b)-c 



a 

b 

c 



a 

b- 
c- 



a+b+c 



a-b-c 



16 



Logic functions and logic gates 



13. a(b+c) = ab+ac 



a 

b. 
c 



a-(b+c) 



a 
b 



a-b+a-c 



14. a+b c = (a+b)-(a+c) 

a+(b-c) 



a 
b 



(a+b)-(a+c) 



15. (a+b) = ab 



a 




a 
b 



(a+b) 




a • b 



a • b 



16. (a b) = a+b 



a 
b 



"^o — (a-b) 



a 
b 



a + b 



b^ 



a + b 



17. («) = a 



a 





a 



a 



-o 




a 



a 




a 



When the logic function is defined using only the basic logic operators (NOT, AND, 
OR), the De Morgan's laws allow to transform easily a logic function into its comple- 
ments. Given the function / it is possible to obtain the negated function / following 
a simple procedure: 

• the original AND operators are replaced with OR operators and vice versa, using 
parentheses to keep the original evaluation order unchanged; 

• all the variables are complemented (negated) with the NOT operator. 
Example: 

/ = a+bc+de+gh 

f = aib+c)id+e)ig+h) 



Logic functions and logic gates 



17 



Please notice that AB is not the same as (A-B). So, writing AB might create 
confusion, because the line above seems to be unique. 



1.10 Sum of produtcs 

A logic function is an expression made of logic variables, logic constants and logic 
operators, which produces a logic result (true or false). However, a logic function can 
be described simply with the truth table that combines the input variable values with 
the expected result for every input combination. 

Having a truth table it is possible to synthesize the corresponding logic function 
through the method known as the sum of products. The sum of products is the 'sum' 
(logic OR) of all the fundamental products that describe every input condition. The 
following picture shows three truth tables with two, tree and four inputs; for every 
input combinations it is written the fundamental product, which is a function that be- 
comes true only with a particular combination. For example, the fundamental product 
A B C (or ABC) describes the combination A=0, B=l and C=0. 



18 



Logic functions and logic gates 



Table 1.16. Fundamental products of functions having two, three and four input 
variables. 



A 


B 


fundamental 
product 


A 


B 


c 


D 


fundamental 

LSI ( /tl ttl_ t 


o 

u 


0 
yj 




AB 


0 


0 


0 


0 


AB C D 


0 


1 




AB 


0 


0 


0 


1 


AB C D 














u 


U 


1 

1 


U 


A T3 T\ 

A d L U 


1 


0 




AB 


0 


0 


1 


1 






ABC D 


1 


1 




AB 


0 


1 


0 


0 


A BCD 


A 

A 


u 
D 


c 


flAYldfiYftPYltfil 

product 


0 
0 


1 
1 


0 

1 


1 

0 


AB CD 
AB CD 


0 


0 


(J 


ABC 


0 


1 


1 


1 


ABCD 


n 


o 


1 


ABC 


1 


n 
u 


0 


0 


a i2 c n 


n 

u 


1 

1 


0 


ABC 


1 


o 


o 


1 


ABCD 


U 


1 
1 


1 


ABC 


1 


0 


1 


0 


ABCD 


1 


0 


0 


ABC 


1 


o 


1 


1 


ABCD 










1 


1 


0 


0 


ABCD 


1 


0 


1 


ABC 










1 


1 


0 


1 


ABCD 


1 


1 


0 


ABC 


1 


1 


1 


0 


ABCD 


1 


1 


1 


ABC 


1 


1 


1 


1 


ABCD 



For example, the function known as NXOR (function of two input variables that is 
true only when the inputs have the same value) is synthesized with the procedure that 
is shown by the following figure. 



Figure 1.17. NXOR function synthesis, starting from the truth table. 
A B 



0 0 

0 1 

1 0 

1 1 



fundamental 
product 



function 
result 



A B 

A B 

A B 

A B 



1 

0 
0 
1 



normal 
synthesis 

>AB 



reversed 
synthesis 



>AB 



B 



A B + A B 



>AB 



>AB 



( A B + A B ) 
AB+AB ~* 



B 



t^yC*^ ( A B + A B ) 



sum of products 



Logic functions and logic gates 



19 



To synthesize a function, the fundamental products corresponding to the expected 
true combinations are added together (sum of products); as the figure shows, it is also 
possible to do the opposite to obtain the equivalent negated function. 

1.11 Karnaugh maps 

A logic function can be translated into a Karnaugh map, which can help to simplify 
the expression that synthesize the function. The Karnaugh map is a bidimensional 
representation of the fundamental products, from the truth table that is to be analyzed. 
In the following figures are shown three empty maps, for functions with two, three 
and four input variables: care must be taken to the fundamental produtcs sequence, 
because it does not correspond to the one used for the truth table. 

Figure 1.18. Karnaugh maps containing the fundamental product definitions per- 
taining to each cell. 



A 


B 


fundamental 
product 


0 


0 




AB 


0 


1 




AB 


1 


0 




AB 


1 


1 




AB 


A 


B 


c 


fundamental 
product 


0 


0 


0 


ABC 


0 


0 


l 


ABC 


0 


1 


0 


ABC 


0 


1 


1 


ABC 


1 


0 


0 


ABC 


1 


0 


1 


ABC 


1 


1 


0 


ABC 


1 


1 


1 


ABC 



\ 


B 


B 




A 


B 


c 


D 


fundamental 
product 


A 


AB AB 




0 


0 


0 


0 


A BCD 










0 


0 


0 


1 


A BCD 


A 


AB AB 


W 


0 


0 


1 


0 


AB C D 










0 


0 


1 


1 


AB C D 










0 


1 


0 


0 


A B CD 






C 


c 


0 
0 


1 
1 


0 

1 


1 

0 


AB CD 
ABCD 










AB 


ABC 


ABC 


0 


1 


1 


1 


A B C D 










1 


0 


0 


0 


AB CD 


AB 


ABC 


ABC 


1 


0 


0 


1 


A BCD 










1 


0 


1 


0 


AB CD 










AB 


ABC 


ABC 


1 


0 


1 


1 


ABCD 










1 


1 


0 


0 


AB CD 


AB 


ABC 


ABC 


1 
1 


1 
1 


0 

1 


1 

0 


ABCD 
ABCD 






llll 


Mllll^- 


1 


1 


1 


1 


A B C D 





CD 


CD 


CD 


CD 


AB 


ABCD 


AB" CD 


ABCD 


ABCD 


AB 


AB CD 


AB CD 


ABCD 


AB CD 


AB 


ABCD 


AB CD 


ABCD 


AB CD 


AB 


AB CD 


ABCD 


ABCD 


ABCD 




II ■■ II 


lll^^ 




II II II 



The maps should be used placing inside the cells a 1 where the fundamental products 
are valid. The following figures show some examples, matching each truth tables with 
the corresponding map. 



« 



20 



Logic functions and logic gates 



Figure 1.19. Truth tables and Karnaugh maps pairs. 



A 


B 








\ 


B 


B 






0 


0 


1 














0 


1 


0 




A 


1 


0 






1 
1 


n 
u 


0 














1 


1 








A 


0 


1 






1 










A 


B 


c 








\ 


C 


c 


0 


0 


0 




1 












0 


0 


1 




1 




AB 


1 


1 


0 


1 


0 




0 












0 


1 


1 




0 




A B 


0 


0 


1 


0 


0 




1 












1 


0 


1 




1 




AB 


1 


0 


1 


1 


0 




1 












1 


1 


1 




0 




AB 


1 


1 



A 


B 


c 


D 




n 
u 


u 


n 
u 


u 


1 
1 


n 
U 




n 
u 


i 
i 


I 

1 


n 
u 


u 


1 
i 


n 


n 
u 


U 


u 


i 

i 


i 

i 


u 


n 


i 

i 


n 


n 
u 


i 

i 




■ 

i 


n 


i 

i 


i 


U 


i 

i 


1 


U 


U 


n 
u 


i 

i 


1 
i 


1 


1 


i 

i 


n 


n 


n 


1 


1 
i 




n 
u 


1 
i 


n 
u 


1 


0 


1 


0 


1 


1 


0 


1 


1 


0 


1 


1 


0 


0 


1 


1 


1 


0 


1 


0 


1 


1 


1 


0 


1 


1 


1 


1 


1 


0 



AB 



AB 



AB 



AB 



CD 


CD 


CD 


CD 


1 


1 


0 


0 


1 


1 


1 


0 


1 


0 


0 


1 


1 


0 


0 


1 



Once the map is prepared, the cells containing the value 1 should be grouped together 
in rectangular shapes, considering different grouping alternatives if possible. Please 
notice that these groups can be only of one, two, four, eight,... elements. 

Figure 1.20. Karnaugh maps with the cells grouped horizontally and vertically; 
the map with four input variables shows two alternative groupings. 



A 


B 








0 


0 


1 




0 


1 


0 




1 


0 


0 




1 


1 


1 




A 


B 


c 






0 


0 


0 




1 


0 


0 


1 




1 


0 


1 


0 




0 


0 


1 


1 




0 


1 


0 


0 




1 


1 


0 


1 




1 


1 


1 


0 




1 


1 


1 


1 




0 



CD 0 

o Q 



AB 
AB 
AB 
AB 



I 1 u 


0 

c > 
1 


0 
0 




0 



A 


B 


c 


D 




0 


0 


0 


0 


1 


0 


0 


0 


1 


1 


0 


0 


1 


0 


0 


0 


0 


1 


1 


0 


0 


1 


0 


0 


1 


0 


1 


0 


1 


1 


0 


1 


1 


0 


0 


0 


1 


1 


1 


1 


1 


0 


0 


0 


1 


1 


0 


0 


1 


0 


1 


0 


1 


0 


1 


1 


0 


1 


1 


0 


1 


1 


0 


0 


1 


1 


1 


0 


1 


0 


1 


1 


1 


0 


1 


1 


1 


1 


1 


0 



CD 



CD 



CD CD 



AB 
AB 

AB 

AB 

\ 
AB 

AB 
AB 
AB 



1 



CD 



CD 



CD CD 



1 



When two adjacent cells — vertically or horizontally — contain the value 1, one of 
the variable regarding the two cell is useless. The following figure demonstrates intu- 
itively the process. 



Logic functions and logic gates 



21 



Figure 1.21. Simplification when two adjacent cells have the value 1. 

B B 



A 


B 




0 


0 


1 


0 


1 


1 


1 


0 


0 


1 


1 


0 


A 


B 




0 


0 


0 


0 


1 


1 


1 


0 


0 


1 


1 


1 




AB+AB =A(B + B) = A-l = A 



a> ~FJ=Oi A>- 



B>- 
A>- 



to- 



B >-*=q 
A>- 





AB+AB =(A + A)B = Bl = B 



A >- 
B >- 



A >-t^ 



B >- 




dd 



B >- 



The simplification comes out from the fact that x OR x is always true; therefore, when 
a rectangular group shows that the same variable appears both normal and negated, 
that variable can be simply ignored. 

Figure 1.22. Example of a map that cannot be simplified. 



A 


B 




0 


0 


1 


0 


1 


0 


1 


0 


0 


1 


1 


1 




► A B 



► A B 



AB+AB 



22 



Logic functions and logic gates 



Figure 1.23. Example with three variables. 



A 

A 


B 


c 




\ 


0 


0 


0 


1 




AB 


0 


0 


1 


1 




0 


1 


0 


0 


AB 


0 


1 


1 


0 




1 


0 


0 


1 


AB 


1 


0 


1 


1 




1 


1 


0 


1 


AB 


1 


1 


1 


0 





C 


C 


1 

I 1 


1 

0- 


0 


0 




r > 
1 


0 


1 


1 


0 



> ABC+ ABC + ABC + ABC-B 



■> AB C + AB C = AC 



t Y 

B+AC 

Figure 1 .24. Example of alternative simplifications with a map having four vari- 
ables. 

CD CD CD CD 



A 


B 


C 


D 


\ 


0 


0 


0 


0 


1 


AB 


0 


0 


0 


1 


1 




0 


0 


1 


0 


0 


AB 


0 


0 


1 


1 


0 




0 


1 


0 


0 


1 


AB 


0 


1 


0 


1 


1 




0 


1 


1 


0 


0 


AB 


0 


1 


1 


1 


1 




1 


0 


0 


0 


1 


\ 


1 


0 


0 


1 


0 


AB 


1 


0 


1 


0 


1 




1 


0 


1 


1 


0 


AB 


1 


1 


0 


0 


1 




1 


1 


0 


1 


0 


AB 


1 


1 


1 


0 


1 




AB 


1 


1 


1 


1 


0 





1 



ABCD+ ABCD+ ABCD+ ABCD= AC 
— ► AB CD + AB CD = ABD 



CD 



CD CD CD 



1 
1 
1 
1 

I J 



f \ 

1 



1 



1 



ABCD+ ABCD+ ABCD+ ABCD= AD 

AC +ABD+ AD 

* ABCD+ AB C D = ACD 

AB CD + AB C D = ABD 
*- ABCD + ABCD = ACD 



ABCD + ABCD + ABCD + ABCD = CD 



ACD+ABD+ACD+CD 
Karnaugh maps allow to simplify a logic function with no more than four variables, 
otherwise the map should have more than two dimensions and it would be impractical 
to view. 

It might happen that the function output for some input combination is unspecified, 
because it doesn't matter what it is. When it happens, the synthesis can decide what 
value is better for the purpose of reducing the final expression. That is: it is free the 
decision whether these values should be grouped or not. 



Logic functions and logic gates 



23 



Figure 1.25. Example of alternative options when simplifying a function with 
some unspecified output values. 



A 


B 


c 


D 




n 

VJ 


n 
vj 


n 


0 

yj 


1 

1 


VJ 


vj 


n 
yj 


1 

J. 


A 


VJ 


vj 


1 

i 


yj 


n 

VJ 


n 

VJ 


n 
vj 


1 
i 


1 
i 


v 

A 


n 

VJ 


1 

i 


n 


0 

VJ 


1 
1 


n 

VJ 


1 

i 


n 

VJ 


1 
i 


1 
1 


n 

VJ 


1 

i 


1 

1 


0 

VJ 


v 

A 


o 

VJ 


1 

J. 


1 

J. 


1 

± 


A 


1 

1 


vj 


n 

VJ 


yj 


Y 
A 


1 

J. 


yj 


n 

VJ 


1 

A. 


n 

VJ 


1 

1 


n 

VJ 


1 

1 


0 


Y 
A 


1 

1 


0 


1 

1 


1 

1 


0 


1 


1 


0 


0 


X 


1 


1 


0 


1 


1 


1 


1 


1 


0 


X 


1 


1 


1 


1 


1 



AB 
A B 

AB 
AB 



p n 


CD 


CD 


CD 




X 


X 


0 






i 


1 


X 


X 


X 


1 


1 


X 


X 


0 


0 


X 



A C D 
B 



} 



B+ACD 



CD 



CD 



CD CD 




A C 



AB 



} 



A C + AB 



CD 



CD 



CD 



CD 



AB 
AB 

AB 
AB 




-►ACD 
— B C 



} 



BC+ACD 



Karnaugh maps can be used also for logic networks with more than one output for the 
same inputs; in that case, these networks are seen as multiple logic functions sharing 
the same input variables: it is probably useful to try to share also some more elements 
inside the two functions as it is shown in the following example. 

Figure 1.26. Two functions of the same input variables, synthesized with two 
maps. 



A 


B 


c 


fa fb 


0 


0 


0 


0 0 


0 


0 


1 


1 1 


0 


1 


0 


0 0 


0 


1 


1 


1 1 


1 


0 


0 


0 0 


1 


0 


1 


0 0 


1 


1 


0 


1 0 


1 


1 


1 


1 0 



AB 
AB 
AB 
AB 



c 


c 


0 




0 


1 

^ J 




\ 


1 


1 

/ 


0 


0 



* AC a 



AC+AB 





C 


c 


AB 


0 


1 




AB 


0 






AB 


0 


0 


AB 


0 


0 



AC 



24 



Logic functions and logic gates 



« 



Figure 1.27. Logic network solution: divided on the left and joined on the right 
(saving a logic gate). 



A>- 

B > 
C> 

A>- 

C > 



> 



A>- 

B> 

C> 



-o 



> 



> 



/b 



1.12 Logic gates and multiple lines 

Designing a complex network it is possible to draw multiple lines together if the 
connected logic is replicated for each one. 



Figure 1.28. Quad inverter. 



7 



A. 



"7 



>o 1 3 



The above example shows four inverters designed in paralel, using on the left a com- 
pact way, where the four input and output lines are joined together in a single multiple 
one. The following figure shows a similar paralel connection with four AND gates. 

Figure 1.29. Quad AND. 



4 



7 



4 



4 

A. 



> 



7 



4 

/ 



4 

/ 



> 



> 



> 



> 



4 



The following figure shows a different kind of line joining, related to multiple input 
gates: the OR gate has four input lines, but on the left the four lines are joined in a 



Logic functions and logic gates 



25 



single multiple one. 

Figure 1.30. Four input OR. 



"7 




A paralel gate connection might require that some ports be connected together to a 
single line. The following figure shows four XOR gates with one of the two input 
ports connected to the same line. 

Figure 1.31. Quad XOR with a common input line. 



4 

7^ 



o 



E> 



4 



1.13 Electronic logic gates 

The logic gates are usually implemented inside integrated circuits (IC), with various 
technologies and densities. During the 1970' s it was commonly used the so called 
discrete logic, made of small integrated circuits with few logic gates or simple specific 
logic circuits. The old 'discrete logic' might give the idea of what can be concretely 
a logic gate in reality. 

Figure 1.32. Four NAND gates inside an integrated circuit. The schematic on 
the left shows that the connections 7 and 14 must be used for the power supply: 
Vcc/Vdd and GND (ground). 

Vcc 



« 



14 



13 



12 



11 




10 





GND 





26 



Logic functions and logic gates 



The boolean algebra consider only three logic states: 0, 1 and 'X', for 'true', 'false' 
and 'unspecified' (unknown). The electronic logic adds another state: 'Z' for 'high 
impedance' or 'floating'. 

Figure 1.33. Tri-state buffer. On the left side the enable line is 'active high'; on 
the right side the enable line is 'active low'. 



enable 


input 


output 


0 


X 


z 


1 


0 


0 


1 


1 


1 



input 




output 



enable 



enable 


input 


output 


0 


0 


0 


0 


1 


1 


1 


X 


z 



input 




output 



enable 



The tri-state buffer, shown above, works like a buffer, replicating the same value 
received from the input to the output, but only when the enable input is asserted, 
otherwise its output becomes virtually 'disconnected'. The state of isolation that the 
tri-state buffer can have on the output, when the enable input is negated, is called 
'high impedance' or 'floating' and is used the letter 'Z' to show it. 

Figure 1.34. The connection of many output lines together is possible with tri- 
state buffers. 



NEVER DO THIS! 




V 



only one enable line 
can be asserted! 



The figure above shows that it is not possible to connect together the output of two 
or more common logic gates, because it is not specified what should happen if these 
output drive a different logic state and because it will damage these components. On 
the right the circuit is modified with the addition of tri-state buffers; this time the 
connection is possible, but only under a strict condition: only one tri-state buffer can 
be enabled. But if no one of the four tri-state buffers is enabled, the last AND gate 



Logic functions and logic gates 27 

on the right receives an unpredictable or confused input, corresponding to the Z state, 
which is neither 0 nor 1 . 

Electronic gates have also another important characteristic: the propagation delay, 
which means that the gates output is always updated with a little delay, compared to 
the input changes. 

Figure 1.35. Delay introduced by a simple inverter gate. 




in 



out 



2 ns 



time 



The figure above shows that even the simplest component, like the inverter gate, intro- 
duces a little delay. In that case it appear a delay of 2 ns. The following figure shows 
that the delay can be used to produce a short pulse. 

Figure 1.36. Pulse signal produced with an inverter delay. 



in 




in 



out 



in 



in 



out 



J 



Jl 



Jl 



a 



b 



c 



Jl 



Jl 



Jl 



Jl 



Jl 



a inverter delay 
b AND gate delay 
c impulse 



It should be noticed that the above example is not practical, because the delay is too 
short to be useful; a longer delay with a sequence of more inverters might solve the 



28 



Logic functions and logic gates 



problem. 
1.14 HDL 

Logic networks can be simply designed in a way that can be read by human. When a 
logic network is to be treated as data, it should be 'designed' adding all the informa- 
tion needed and not just only the graphical aspect, whereas the graphical aspect might 
also be unnecessary and omitted. There are specific languages (just like the common 
programming languages) used to describe the logic networks and, more generally, the 
hardware. These are known as hardware description languages and the abbreviation 
HDL is commonly used. 

There are two main HDL languages: VHDL and Verilog. Here is used Verilog because 
of its closeness to the C language, allowing to show examples without a previous 
detailed study of the language. 

As a first example of Verilog coding it is shown how a simple AND gate could be 
synthesized. Verilog defines modules that are intended like black boxes with input and 
output ports, modules declared like they were functions; here the module is declared 
with the name my_and, because the name 'and' is obviously reserved. 

Figure 1.37. The module my_and that is to be synthesized with Verilog. 



my_and 







AO 








1 ) 


> 









The first solution in Verilog code is very simple and it uses a 'continuous assignment' 
with a little delay (6 ns) to reproduce the propagation delay that real gates have. 



Listing 1.38. Verilog code implementing the myjxnd module with a continuous 
assignment. 



^timescale Ins 




module my_and (Y, A, B) ; 




input A, B; 




output Y; 




assign #6Y=A&B; 


// continuous assignment 



Logic functions and logic gates 



29 



endmodule 



A very simple variation of the above example consists on the use of a gate instantia- 
tion, which is named AO; like the previous example it is specified a 6 ns delay. 



Listing 1.39. Verilog code implementing the my_and module with a gate instan- 
tiation. 



^timescale Ins 




module my_and (Y, A, B) ; 




input A, B; 




output Y; 




and #6 AO (Y, A, B) ; 


// gate instantiation 


endmodule 





The two example above declare the module myjxnd and specifies that A and B are in- 
put ports (wires), whereas Y is an output port. Then, on the first example it is assigned 
to the Y wire the result of A B, with a 6 ns delay, whereas on the second example 
it is used a gate instantiation with the same delay. Please notice that the continuous 
assignment of the first example and the gate instance of the second just work contin- 
uously: every time that A or B change value, after the specified delay they update the 
value assigned to Y. 

A more complex solution might requires to use a memory, defining that the output 
line is the output of a virtual register with the same name. This virtual register works 
like a local variable of a single bit. 



Listing 1 .40. Verilog code implementing the my_and module with a propagation 
delay of 6 ns. 



'timescale Ins 




module my_and (Y, A, 


B) ; 


input A, B; 




output Y; 




reg Y ; 


// virtual register 


always @ (A or B) 


// do if A or B change value 


begin 




# 6; 


// propagation delay 



30 



Logic functions and logic gates 



Y = A & B; 


// assign the result to Y 


end 




endmodule 





The above code, after the module ports declarations, specifies that the Y wire comes 
from a register, so that the value of Y should be changed assigning something to it 
(inside a block). Then it start a block delimited by the keywords begin and end, 
which is executed every time that at least one of the input ports (A and B) changes 
its value. This block starts with a 6 ns pause, then the bitwise A B is calculated and 
assigned to Y. 



Chapter Z. 

Introduction to Verilog 

« 





2.1 


Minimal notions 


33 




2.2 


Hello world! 


33 




2.3 


Compiler directives 


38 




2.4 


Signal values 


41 


bera.ni 


2.5 


Literal constants 


41 


aticali 


2.6 


Data types 


43 


nform 


2.7 


Ports 


46 


fin 

£ 


2.8 


Parameters 


48 


2.9 


Module declarations 


48 


u 
£ 


2.10 


Module instance 


51 


© 


2.11 


Fully qualified path names 


51 


ippun, 


2.12 


Primitives 


52 


liele Giacomini — i 


2.13 


Expressions 


54 


2.14 


Vector and array addressing 


58 


2.15 


Strings 


59 


©Dai 


2.16 


Functions 


60 


.ftp 


2.17 


Netlist modules: combinational circuits 


62 


f 


2.18 


Behavioral modules 


68 


5 


2.19 


Procedural assignments 


69 


ift-20] 


2.20 


Blocking delays 


71 




2.21 


Wait for a level event 


72 


ound u 


2.22 


Wait for an event expressions 


74 


the gr 


2.23 


Event variables 


76 


1 


2.24 


System tasks and functions 


76 



32 



Introduction to Verilog 



2.25 Control structures 



78 



2.26 Thread control 



81 



51 ! 54 ! = 54 ! == 54 * 54 */ 33 + 54 . 33 / 54 /* 33 // 33 ; 33 == 54 === 54 
?: 54 addressing 58 always 68 and 52 array 43 58 assign 62 assignment 69 
begin 68 behavioral module 68 bit range 58 bit size 43 58 blocking assignment 69 
buf 52 buf if 0 52 bufifl 52 case 78 casex 78 casez 78 combinational 
circuit 62 control structure 78 data type 43 defparam 51 delay 71 directive 38 end 
68 endmodule 48 event 43 76 event expression 74 expression 54 floating point 
number 41 for 78 forever 78 fork 81 function 60 gate instance 52 HDL 31 if 
78 initial 68 inout 46 input 46 integer 43 integer number 41 join 81 
level event 72 literal constant 41 macro 38 memory 43 module 48 module instance 
51 nand 52 net 43 netlist module 62 non-blocking assignment 69 nor 52 not 52 
notif 0 52 notif 1 52 nxor 52 or 52 output 46 parameter 48 port 46 
primitive 52 primitive instance 52 procedural assignment 69 real 43 reg 43 
repeat 78 scalar 43 signal 41 string 41 59 supplyO 43 supplyl 43 switch 
instance 52 symbolic macro 38 system function 76 system task 76 thread 68 
thread 81 time 43 top level module 48 tri 43 triO 43 tril 43 triand43 
trior 43 variable 43 vector 43 58 Verilog 31 wait () 72 wand 43 while 78 
wire 43 wor 43 x41 xor 52 z 41 & 54 && 54 @ 74 A 54 ~ 54 ~& 54 ~" 54 ~ | 54 
I 54 | | 54 { { } } 54 { , } 54 $display () 33 76 $finish 76 $finish () 33 
$monitor ( ) 76 $time 76 - 54 < 54 <= 54 << 54 <<< 54 > 54 >= 54 » 54 
»>54 % 54 "define 38 "else 38 "endif38 "ifdef38 A ifndef38 
"timescale 38 

Logic networks can be simply designed in a way that can be read by human. When a 
logic network is to be treated as data, it should be 'designed' adding all the informa- 
tion needed and not just only the graphical aspect, whereas the graphical aspect might 
also be unnecessary and omitted. There are specific languages (just like the common 
programming languages) used to describe the logic networks and, more generally, the 
hardware. These are known as hardware description languages and the abbreviation 
HDL is commonly used. There are two main HDL languages: VHDL and Verilog. 
Verilog has the advantage to be more terse and similar to the C language. 

When an HDL language is used, the project usually has two purpose: simulation 
and synthesis. Simulation is used to verify the project with a software tool; synthesis 



Introduction to Verilog 



33 



is made to obtain some specific code for programmable hardware or to produce a 
final integrated circuit. When using an HDL language, some code might have specific 
meaning for the simulation that the synthesis phase might ignore. 

To verify the examples of this chapter, the TKGate and Icarus simulation environ- 
ments might be used (http://www.tkgate.org , http://iverilog.icarus.com ). 

2.1 Minimal notions 

There is some similarity between Verilog and the C language, but Verilog is not C 
and the resemblance is limited to some aesthetics. The first minimal notions to start 
reading the Verilog code are the following: 

• comments are the same as C (/*...*/ and //); 

• white spaces are ignored unless they are delimited as string constants; 

• the semicolon ( ; ) is used to terminate the statements and the comma ( , ) is used 
to separate elements inside a list; 

• identifiers (the names used to identify components defined inside the code) are 
case sensitive and should start with a letter or the underscore (_) and might contain 
letters, digits, underscore (_) and dollar ($);* 

• all Verilog keywords are lowercase. 

2.2 Hello world! 

A first minimal program is useful to test the simulation environment. The Verilog 
language includes some functions and instructions whose name start with dollar ($), 
functions and instructions that are intended to control the simulation environment. 
The typical simulation environment should have the ability to display some text that 
Verilog can output with the $display () function, which works in a similar way to 
the print f ( ) found in C. 



34 Introduction to Verilog 



Listing 2.1. Two times "Hello world!". 



modi] 1 p hp 1 1 o: 




initial 




hpa i n 




Srii ^nl ^iv ( "Hp! 1 n 


W^_JJ__l_kJ.. 1 f 


Sdisclav ("Hello 


world ' " ) ; 


#10 $finish; 




end 




endmodule 





The example listed above shows two times the text "Hello world!", then it waits 10 
time units and then it stops the simulation with the $f inish instruction. Please notice 
that the $display ( ) function adds a new-line at the end of the string and the double 
display is intended to show this feature. It is supposed that the file containing the 
above listing is named 'hello . v'; to run TKGate with it, the following command 
might be used: 



$ tkgate20 hello .v [Enter] 



Introduction to Verilog 



35 



Figure 2.2. TKGate after the program end. 

File Edit Tool Format Module Components Help 



D BHD 



M 



||i|Tree |s I List 

|-@ hHta 
{ Libraries 



Nets 



Ports 



IT 



X3 



OEdit 



@ 



Interface 



Simulate 



modulo hello; 

initial 
begin 

Sdisplay ("Hello world I ") ; 
Sdisplay ("Hello world I ") ; 
#10 $finish; 
end 
©ndmodule 



TkGate 2.0-blO - Digital Circuit Editor and Simulator (released Sep 26 2009) 

[Compiled Jul 27 2012 23:00:50] 

Copyright (C) 1987-2009 by Jeffery P. Hansen 

TkGate comes with ABSOLUTELY MO WARRANTY ; see ' Help. .. License ' menu 
for license and warranty details. Report problems to hansen@tkgate.org 

[Loaded VPDs: CokeMachine TTY KBD SCR] 

Starting simulator at Wed Jan 23 19:58:45 2013. 

Hello world! 

Hello world! 



File: hello. v 



Module: hello 



The above example might be also compiled and tested with Icarus Verilog in the 
following way: 

$ iverilog -o hello, vvp hello .v [Enter] 

The above command generates the file 'hello. vvp' that can be executed by the 
command vvp: 

$ vvp hello.wp [£^er] 



Hello World! 
Hello World! 



This video shows how to replicate the above example, with TKGate and with 
Icarus Verilog, starting from the same source 'hello.v': ogv http://www.youtube. 
com/watch 7v=kGofhPGWErc . 



36 



Introduction to Verilog 



To use a Verilog simulation environment it is also necessary to be able to trace a 
wave at some point, to see dynamically what happens inside some virtual wires. The 
next example is made to generate two different clock signals at the variables x and y 
(these variables represent a wire with memory and it doesn't matter how it should be 
implemented). 

Listing 2.4. Two different clock signals. 

module wave; 
reg x; 
reg y; 
initial 
begin 

$dumpf±le ("wave.vcd") ; 
$dumpvars (0, wave) ; 

x = 0; 
Y = 0; 
end 
always 
begin 

# 20; 
x = 1; 

# 20; 
x = 0; 

end 
always 
begin 

# 15; 

y - i; 

# 15; 
y = 0; 

end 
endmodule 



The above listing contains two simulation functions necessary to Icarus Verilog to 
create the 'wave . vcd' with all the variables variations; this file is then read by GTK- 



Introduction to Verilog 



37 



wave. The following command assumes that the above listing is contained inside the 
file wave . v : 

$ iverilog -o wave . wp wave.v[£nfer] 
$ wp wave . wp [ Enter ] 

The simulation does not stop by itself and it is necessary to send an interruption signal 
with the keyboard combination [ Ctrl c ] . 

$ [Ctrlc] 

Then wp turns to work in interactive mode and it is necessary to type the command 
finish: 

> finish [Enter] 

At this point there is the file 'wave . vcd' and it can be read with GTKwave: 
$ gtkwave wave.vcd[£«ter] 

Figure 2.5. GTKWave with the variable x and y selected. 

File Edit Search Time Markers View Help 



C£)Qj(0^(±^G^ fi^^l] >- From:|o se: To:|21950320 s Marker: -- | Cursor: 5452375 sec 



- SST 



r 



Type Signals 



reg x 



reg y 



Filter: 



Append Insert Replace 



■ I 



Waves 




a _i d 

The picture above shows GTKWave with the variables x and y already selected. To 
do so, on the left the module name (wave) must be selected, then the variable names 
appear just below: the variable names must be dragged and dropped into the black 
window that should show the waves. 



TKGate can use the same source example, but it does not know the functions 
$dumpfile() and $dumpvars(), so these lines must be removed or commented. 



38 

$ tkgate20 wave . v [ £>iter ] 



Introduction to Verilog 



« 



The following picture shows TKGate running the simulation with a 'scope' window 
showing the waves, selected from the net list on the left. 

Figure 2.6. GTKWave with the variable x and y selected. 




Simulate Module Help 



ol ii oIgg w ai j I ii fr m • t m 
;e itl 

ii Librari 



If 



OEdit | 03 Interface 



Nets Ports 























Simulate 



TkGate: Scope 



module wave 



r e g :■: ; 
rog y; 
initial 
begin 

//$duapt i ie ("wave, vcd") ; 

■>( -ri z s ( 0, iv«a J ; 
x = 0; 
y = 0; 
end 
always 
begin 

# 20; 
x = 1; 

# 20; 
x = 0; 

end 
always 
begin 

# lb; 
y = l; 

4 15; 



File Sim ulate Trace Help 



f, O DO £U S*J J ftlMiiffi 



File: wave.v 



Module: wave 



42. 846us 



+10 +20 +30 t40 +S0 +60 +70 +80 +90 +100 

J ' 



This video shows how to replicate the above example, with Icarus Verilog and 
TKGate, starting from the same source 'wave.v': ogv http://www.youtube.com/ 
watch 7v=NLzcXuadiIQ . 

2.3 Compiler directives 

The C language has a pre-compiler that looks for directives like #define and 
#ifdef . The Verilog language has similar directives that starts with the character 
' (back quote). Like in the C language, the compiler directives do not have the final 
semicolon. 

Like in the C language there is a 'define directive to declare a symbolic macro: 



* de f i n e macro replacing Jext 



Introduction to Verilog 39 

For example, the symbolic macro 'MY_MACRO representing the value 45 could be 
declared as: 

'define MY_MACRO 4 5 

To use the symbolic macro inside an expression, it must be used with the ' prefix, 
like this: 

x = a + > MY_MACRO; 

Like in the C language there are the directives 'ifdef, 'ifndef, 'else and 
'endif , to conditionally select the Verilog code. 



* i f de f macro 

code_if_macro_exists 

'else 

alternative _code 

'endif 



'ifndef macro 

code_if_macro_does_not_exist 

'else 

alternative^ ode 

'endif 



See the following example: 



40 



Introduction to Verilog 



'ifdef MY_MACRO 

x = a + > MY_MACRO; 
^else 

x = a; 
^endif 

In the above example, the variable x is the sum of a and the macro 'MY_MACRO, but 
only if the macro itself is already declared. The next example is just the opposite, but 
with the same meaning: 

'ifndef MY_MACRO 

x = a; 
^else 

x = a + > MY_MACRO; 
^endif 

The Verilog language requires the definition of the time scale, which is the minimal 
time unit used for the simulation. The timescale is defined with the 'timescale 
directive: 



'timescale integer _delay_unit \ / max resolution 



The integer delay unit time and the max resolution are specified with values that 
should be 1, 10 or 100 followed by "s" (seconds), "ms" (milliseconds), "us" (mi- 
croseconds), "ns" (nanoseconds), "ps" (picoseconds) or "fs" (femtoseconds). 

^timescale lOns/lns 

The above example requires that the simulation is made with a precision of 1 ns, 
whereas the integer delays are 10 ns multiples, but this means that a delay of 1 is 
10 ns long and a decimal delay time can be specified, up to the first decimal position. 
For example, a delay of 1.3 is equal to 13 ns, but 1.35 is also equal to 13 ns, because 
the minimal resolution is of 1 ns. The following example specifies that only integer 
delays notations are allowed (1 ns): 



A timescale Ins 



Introduction to Verilog 



41 



2.4 Signal values 

Verilog consider four 'logical' states: 0, 1, unknown and floating (hi-impedance). The 
states 0 and 1 are the well defined logic values; if the logic value is unknown or it 
is not possible to establish it, the symbol x or x can be used to express it. If a wire 
becomes isolated from the other connections, the symbol z, z or ? can be used to 
describe it. 



0 


logical 0 


X 


X 


unknown or unspecified 


1 


logical 1 


z 


Z 


? floating (high impedance) 



2.5 Literal constants 

A literal constant is a constant value represented directly by its value. There are 
three types of literal constants that Verilog can expect: integer numbers, floating point 
numbers and strings. 

The literal constant representing an integer number inside Verilog is much different 
from the common programming languages, because it can contain the bit-range, or 
size: 2 



[ [ size ] ' base ' 


value 




[ [size] ' b 


o 


d | h] value 



The base is a letter specifying the base in which the following number is represented, 
but it is always preceded by an apostrophe. The allowed bases are: ' b, binary; ' o, 
octal; 'd, decimal; 'h, hexadecimal. Here are some examples with size and base 
specified: 



7 ' d32 - 7-bit 32 



42 



Introduction to Verilog 



7'd232 - 7-bit 104i 0 3 

15 ' h3B4F - 15-bit 3B4Fi 6 

5'blll01 -5-bit lllOh 

If the size of the value is not specified, a default size is used, but it depends on the 
implementation and it should be at least of 32 bits (although it is not guaranteed). 
Here are some more examples without size specification: 

'd32 -32i 0 
'd232 -232i 0 
' h3B4F - 3B4Fi 6 
'blllOl - IIIOI2 

If even the base is not specified, it is intended to be a decimal value. 

A literal constant can contain some underscore characters, which are ignored and are 
useful only to separate the digits for some aesthetical reasons: 

i6'boioi_oioo_iiio_ioii-oioioioonioion 2 

The integer representation shown above is related to unsigned numbers, which might 
be extended as unsigned numbers. The current Verilog standard allows also to specify 
signed numbers, but the handling of signed numbers is not simple and it is useful to 
avoid it in the beginning. 

When the base is not decimal, the number can contain also unknown or floating val- 
ues, but these particular values are extended if not all the requested bits are specified: 

16' hlx2x - 0001xxxx0010xxxx 2 
16 ' hx2x - xxxxxxxx0010xxxx 2 
8'blOzzlO -0010zzl0 2 
8 ' bzzlO - zzzzzzl0 2 



A floating point literal constant is represented as a decimal value with decimal point; 
for example: 0.123, 1.23, 12.34. It is the implementation that decides in which 
way it is encoded internally and the bit size that it should have. 



Introduction to Verilog 



43 



Strings are represented in double quotes. Each character inside the string occupies 
8 bits and is encoded following the ASCII standard. For example: a string made of 
three characters requires 24 bits. Strings can contain a subset of the C language escape 
sequences: \n, \t, \\, \" and \ooo (the last escape sequence is a character defined 
by the octal code). 

2.6 Data types 

The Verilog language has many different 'things' that can represent data, divided into 
three main categories: nets, variables and events. Nets are just wire connections that 
can be driven with some value, but they cannot store it; variables are components 
(connected with wires) that can hold and keep a value; events are special variables 
used to hold the triggering of an event. 

Net types represent wires that can have a value only when they are driven by some 
output. If a wire is driven by more than one source with different values, then there is 
a collision and the result on the wire is different, depending on the particular net type. 



Table 2.14. Net types. 



Type 


Description 


wire 


A simple wire used to connect components: collisions result in un- 
known value. 


wand 


A wired AND net: collisions result in the AND of the values driven 
to the net. 


wor 


A wired OR net: collisions result in the OR of the values driven to 
the net. 


t ri 


Just the same as wire, emphasizing the fact that there can be also the 
floating state. 


triO 


A wire where a floating state is changed into 0. 


tril 


A wire where a floating state is changed into 1 . 


t riand 


Just the same as wand, emphasizing the fact that there can be also the 
floating state. 


trior 


Just the same as wor, emphasizing the fact that there can be also the 
floating state. 



44 



Introduction to Verilog 



Type 


Description 


t rireg 


A wire connected to a virtual capacitor, which can retain the last 
value if it is driven by a floating state. 


supplyO 


A wire directly connected to the ground, resulting always into the 
value 0. 


supplyl 


A wire directly connected to Vcc (or Vdd), resulting always into the 
value 1. 



Variable types represents registers and other type of containers to which a value can 
be assigned. 

Table 2.15. Variable types. 



Type 


Description 


reg 


A variable that can be used to represent a hardware register. 


integer 


A 2's complement signed integer variable not intended to represent 
a hardware register, which should have at least a 32-bit size. 


real 


A floating point (signed) variable not intended to represent a hard- 
ware register, which should have at least a 32-bit size. 


time 


An unsigned integer variable, with at least a 64-bit size, useful for 
saving the time counted as a number of simulation time units. It is 
used to hold the value returned by the $time system variable. 



The declarations of nets and reg type variables can be related to a single bit or to a 
numbered range of bits (the types integer, real and time have an implied bit size). 
The following examples show the declarations of nets and registers with a single bit 
size: 



wire wl, 


w2 , 


w3 ; 


// wl, w2, 


w3 and w4 are nets of type 


wire w4 ; 






// 'wire'. 




supplyO 


w5 , 


w6 ; 


// w5 and 


w5 are nets of type "supplyO ' . 


supplyl 


w7 ; 




// wl is a 


net of type 'supplyl' . 


reg rl, 


r2 ; 




// rl, r2 


and r3 are variables of type 


reg r3; 






// 'reg'. 





To declare a 'word' of more than one bit, a range of bits is added before the name of 



Introduction to Verilog 



45 



the net or register. This range is enclosed in square brackets, as the following syntax 
should explain: 



[ msb : Isb ] 



For example, the following declaration defines the 16-bit wires wl6a and wl6b: 



wire [15:0] wl6a, wl6b; 



For a better compatibility, the range should always start from bit zero, up to size -I, 
like the example above. 



When a net or reg is declared as a single bit, it is known as a 'scalar', whereas when 
it is declared with a bit size it is known as a 'vector' . 

A net or variable, either scalar or vector, might be declared as an array, adding a range 
of elements in square brackets after the name, and if the array is of type reg it is also 
called a memory : 



name [ index _1 : index _n ] 



The following example shows a memory made of an array of register vectors: 



reg [7:0] mem [ 0:255]; 

The memory mem is made of 256 8-bit cells, where the first cell is reached with the 
index 0 and the last with the index 255. 



For a better compatibility, the index range should always start from cell zero, up to 
size -I, like the example above. 



To access an array element an index is used, in square brackets, just like the C lan- 
guage does. The index might be a literal constant or an expression that produces an 
integer value. 



46 Introduction to Verilog 

Table 2.19. Event type. 



Type 


Description 


event 


A variable that can be set (triggered) to represent an event. 



The event type is a single particular one that is used to store the triggering of an event. 
This kind of variable is read only inside an event expression and when it is read it loses 
the trigger previously stored. At the moment it is useful to know just how an event 
variable is declared; the following example shows the creation of the event variable 
e: 



event e; 

2.7 Ports 

Almost all the Verilog code must be contained inside a module. A module is some- 
thing like a box connected to the external world through ports. So, a port is a con- 
nection that can be used to get data into the module (input), to put data out of the 
module (output) or to get and put data (inout). 

When declaring a new module the port list should appear in parenthesis, but then it 
must be specified the direction of these ports. The example below shows the declara- 
tion of the module my_module with three ports, named a, b and c, used respectively 
for input, output and both: 



module my_module (a, b, c) ; 
input a; 
output b; 
inout c; 

endmodule 

As it can be seen from the example above, the keywords input, output and inout 
are used to declare a port, with its direction. But ports might have a size bigger than a 
single bit, in that case, the size is specified in the same way as for nets and registers. 



Introduction to Verilog 



47 



module my_module (a, b, c) ; 
input [3:0] a; 
output [2:0] b; 
inout [1:0] c; 

endmodule 

The above example shows that all the ports are vectors of various sizes. Please notice 
that there are no port arrays. 

A port is a connection that, inside the module, might work as a net or as reg, but this 
fact should be specified, otherwise it is assumed that the internal connection is seen 
as a type wire. 



module my_module (a, b, c) ; 
input [3:0] a; 
output [2:0] b; 
inout [1:0] c; 
reg [2:0] b; 

endmodule 

The above example shows that the port b is driven by the module with a memory 
(might be a register). The same declaration might be done at the same time of the port 
declaration, in a more elegant way: 



module my_module (a, b, c) ; 
input [3:0] a; 
output reg [2:0] b ; 

inout [1:0] c; 

endmodule 



48 



Introduction to Verilog 



2.8 Parameters 

Verilog allows to declare symbolic constant, known as parameters. The parameter 
declaration must specify also the value that it represents, with a literal constant or 
with an expression where literal constants and other parameters can be used. 



module 




parameter 


DLY = 3; 


parameter 


XDLY = 3 + DLY; 


endmodule 





The above example shows the declaration of the parameter DLY with the value 3 and 
the parameter XDLY with the value 6. 



The parameters allow to define 'parameterized' modules, so that, for example, the 
size of a net or reg can be defined when a module is instantiated. These details are 
described in the following sections, about module declaration and module instantia- 
tion. 

2.9 Module declarations 

Verilog requires that any circuit or procedure be contained inside a module. There 
must be at least a top level module that might use other modules. Verilog treats mod- 
ules as classes of an object-oriented languages and, except for top level modules, the 
other modules are used after their instantiation. Please notice that any module that is 
never instantiated is a top level module. 



Introduction to Verilog 



49 



module name [ (port_name [, •••] ) ] ; 

[ declarations ] 

[assign assignment^ 

[ primitive instantiation ] 

[module instantiation^ 

[initial block^ ■■■ 

[always block^ ■■■ 
endmodule 



The syntax above shows the declaration of a module: it is important to notice the 
position of the semicolon and the absence of it after the keyword endmodule. 

A module has usually ports, to communicate with the outside, except for the root 
module that does not requires them. If ports are present, their name should be listed 
inside parentheses, but the listed ports must also be declared specifying their direction 
and their data type. 



module my_module (a, b, c) ; 
input [7:0] a; 
output reg [7:0] b; 
inout [15:0] c; 

endmodule 

The above example declares the module myjnodule with three ports: a for input, b 
for output and c for input-output. The port b is declared of type reg, where the other 
ports are implicitly of type wire. 

Usually after the port directions and data type declarations, nets and variables might 
be declared, whereas parameter declarations might be better placed even before the 
port directions, like the following example: 



50 



Introduction to Verilog 



module my_module (a, b, c) ; 
parameter N = 8; 
parameter M = N * 2; 
input [N-1:0] a; 
output reg [N-1:0] b; 
inout [M-1:0] c; 
wire wl, w2; 
reg rl, r2, r3; 

endmodule 

The parameter declaration might also appear in-line, before the port list inside paren- 
theses, like the following examples, where two different methods are used: 

module my_module # (parameter N = 8, parameter M = 16) (a, b, c) ; 
input [N-1:0] a; 
output reg [N-1:0] b; 
inout [M-1:0] c; 
wire wl, w2 ; 
reg rl, r2, r3; 



endmodule 



module my_module # ( . 


N(8) , .M(16) ) (a, b, c) ; 


input [N-1:0] a; 




output reg [N-1:0] 


b; 


inout [M-1:0] c; 




wire wl, w2; 




reg rl, r2, r3; 




endmodule 





Introduction to Verilog 



51 



2.10 Module instance 

To use a module it must be instantiated, creating a module instance. For example, 
the following code creates the module instance mymol from the module my_module 
defined at the previous section end: 



my_module mymol (xl, x2, x3); 

The module instance mymol of the example above, connects the nets or variables xl , 
x2 and x3 to the original ports a, b and c, following the same order. To be more clear 
the module instance connection might be specified, like the following example: 



my_module mymol ( .a (xl) , . b(x2), . c(x3)); 

A module instance can change some parameter values. If the parameters are specified 
in-line, inside the module declaration, like the last examples of the previous section, 
the module instance can be obtained as the following example shows: 



my_module #(16, 32) mymol ( .a (xl) , .b(x2), .c(x3)); 

On the above example, the instance mymol is created assigning to the first parameter 
the value 16 and to the second the value 32. To be sure to select the right parameter 
the following variation might be used: 



my_module #(.N(16), .M(32)) mymol (.a(xl), .b(x2), .c(x3)); 

If the parameters are not specified in-line in the module declaration, they can be mod- 
ified after the module instance is created, with the defparam instruction: 



my_module mymo2 ( .a (xl) , . b(x2), . c(x3)); 
defparam mymo2.DLY = 7; 

The above example shows the instantiation of the module myjnodule and then, to 
the parameter DLY of the newly created instance is assigned the value 7. 

2. 1 1 Fully qualified path names 

When the modules are designed properly, the only way to communicate with them is 
through ports. If, for some reason, it is necessary to access directly to an internal net 
or variable of an instantiated module, it is possible to use a fully qualified path name. 
In fact, this approach might be appropriate for debugging purposes. 



52 



Introduction to Verilog 



module main; 

mymo3 myl (•••) ; 
endmodule 



module mymo3 (•••) ; 

mymo4 myl (...) ; 
endmodule 



module mymo4 (...) ; 

reg rl; 
endmodule 



The above example shows the declaration of the top level module main, where an 
instance of the module mymo3 is created with the name myl . Then, the module mymo3 
contains the creation of an instance of the module mymo4 with the name myl (again). 
The module mymo4 contains the declaration of a reg type variable with the name rl . 
To specify the variable rl of the module mymo4 when instantiated in the described 
way, the following full path might be used: 



ma i n . my 1 . my 1 . r 1 

2.12 Primitives 

The Verilog language has already available some modules describing the common 
logical functions and circuits: these modules are called primitives. There are gate 
primitives that simulate a complete logic gate, and switch primitives that simulate the 
internal component of an electronic gate. 



and myandl (y, a, b) ; 



Introduction to Verilog 



53 



The above example shows the creation of the instance myandl that is a logic AND, 
receiving input from the nets or registers a and b , driving output to the y connection. 
The instance creation might also contain a delay, for simulation purposes: 



and # (5) 


myandl 


(y, 


a, b) ; 


and #(5,7) 


myand2 


(z, 


c, d) ; 



As it can be understood, the delay is specified as a parameter value: if only one pa- 
rameter is specified the delay is for rising and falling edges, otherwise the first value 
is the delay after the rising edge and the second for the falling one. 



Gate primitives have in common the first gate argument being the output, while the 
other being the inputs, which usually can be one or more than one. For example, a 
logic AND with five inputs might be instantiated as shown by the following example: 



and myand3 (y, a, b, c, d, e) ; 

The Verilog primitives are single bit, but the instantiation can be requested for an 
array of the selected primitive. For example: 



and myand4[7:0] (y, a, b) ; 

In that case, the array instance myand4 is created, made of eight and primitives in 
paralel. 



Table 2.43. Gate primitives. 


Primitive 


Ports 


and {output, input [, input] - ) 




or (output, input [, input] ■) 




xor (output, input [, input] - ) 


Logic AND, OR, XOR, NAND, NOR and 


nand (output, input [, input] ) 


XOR. 


nor (output, input [, input] ) 




nxor (output, input [, input] ) 





54 



Introduction to Verilog 



Primitive 


Ports 


buf (output, input) 
not (output, input) 


Buffer and inverter. 


buf if 0 (output, input, control) 
buf if 1 (output, input, control) 
not if 0 (output, input, control) 
not if 1 (output, input, control) 


Tri-state buffers and tri-state inverters. 


pull up (output) 
pulldown (output) 


Output equal to logic 1 or equal to logic 0. 



Figure 2.44. Tri-state buffer and inverter primitives. 




There are occasions when primitives can be instantiated without assigning a name to 
the instances, because it is not worth knowing that name. In that case the instantia- 
tions looks like a function call, but they are not functions and cannot be used inside 
expressions. 



2.13 Expressions 

The Verilog expressions are similar to those of the C language, even for the operator 
precedence and the use of parenthesis to force evaluation order. When the bit sizes of 
operands do not match, then the bit size of the largest value is used and every operand 
is extended to that size before the expression is evaluated. 



Introduction to Verilog 



55 



Table 2.45. Verilog expression operators, grouped by precedence, starting from 
the highest priority, ending with the lowest one. 



Operator 


Description 


{a, b[, c] •••} 


Concatenation - concatenates the bits of two or more 
aaia oojects i^nets or registers^ or expressions reiurn- 
ing a data object. Please notice that a is located at 
the least significant position. 


{«{«}} 


Replication - concatenates n times a. The value n 
must be a constant. 



Operator 


Description 


\a 


Logic NOT - it returns 0 if a is not equal to zero, 1 if a is equal to 
zero. 


~a 


1 ' s complement of a . 


-a 


2's complement of a. 


&a 


Reduction AND - if all the bits of a are set to 1, then returns 1, 
otherwise returns 0. 


I a 


Reduction OR - if all the bits of a are cleared to 0, then returns 0, 
otherwise returns 1 . 


A a 


Reduction XOR - if there is an odd quantity of bits set to one, then 
returns 1, otherwise returns 0. 




Reduction NAND - if all the bits of a are cleared to 0, then returns 
1, otherwise returns 0. 


~ I a 


Reduction NOR - if all the bits of a are set to 1, then returns 0, 
otherwise returns 1 . 




Reduction NXOR - if there is an odd quantity of bits set to one, then 
returns 0, otherwise returns 1. 




Operator 


Description 


a*b 


Multiplication - returns the product of a and b . 


a/b 


Division - returns the quotient of a and b . 



56 



Introduction to Verilog 



Operator 


Description 


a%b 


Remainder, modulo - returns the remainder of alb. 




Operator 


Description 


a+b 


Addition - returns the sum of a and b . 


a-b 


Subtraction - returns the difference of a and b. 




Operator 


Description 


a»b 


Logical right shift - returns the value of a shifted right b times. 


a«b 


Logical left shift - returns the value of a shifted left b times. 


a»>b 


Arithmetic right shift - returns the value of a shifted right b times, 
arithmetically. 


a«<b 


Arithmetic left shift - returns the value of a shifted left b times, 
arithmetically. 




Operator 


Description 


a>b 


Greater then - returns 1 if a is greater than b , otherwise returns 0. 


a<b 


Less then - returns 1 if a is less than b, otherwise returns 0. 


a>=b 


Greater then or equal - returns 1 if a is greater than or equal to b, 
otherwise returns 0. 


a<=b 


Less then or equal - returns 1 if a is less than or equal to b , otherwise 
returns 0. 




Operator 


Description 


a==b 


Equality - returns 1 if a and b are equal and 0 if they are not. Returns 
unknown (x) if any bit inside a or b are unknown or floating (z). 



Introduction to Verilog 



57 



Operator 


Description 


a \=b 


Tnenualitv — returns 0 if a and h are enual and 1 if thev are not 
Returns unknown (x) if any bit inside a or b are unknown or floating 

(*). 


a===b 


Case equality - returns 1 if a and b are exactly the same, included 
unknown and floating bits, otherwise it returns 0. 


a\==b 


Case inequality - returns 0 if a and b are exactly the same, included 
unknown and floating bits, otherwise it returns 1. 




Operator 


Description 


a&b 


Bitwise AND - returns a AND b, bit by bit. 


a~&b 


Bitwise NAND - returns (a AND b), bit by bit. 




Operator 


Description 


a^b 


Bitwise XOR - returns a XOR b, bit by bit. 


a~^b 


Bitwise NXOR - returns (a XOR b), bit by bit. 




Operator 


Description 


a | b 


Bitwise OR - returns a OR b, bit by bit. 


a~ \ b 


Bitwise NOR - returns (a OR b), bit by bit. 




Operator 


Description 


a&Scb 


Logical AND - returns 1 if a and b have both a value different from 
zero, otherwise it returns zero. If there are unknown or floating bits, 
it might be impossible to determine the result: in that case the result 
is unknown as well. 



58 



Introduction to Verilog 



Operator 


Description 


a \ \ b 


Logical OR - returns 1 if either a or b contains a value different from 
zero, otnerwise ii returns zero. 11 mere are unKnown or noatmg diis, 
it might be impossible to determine the result: in that case the result 
is unknown as well. 




Operator 


Description 


alb :c 


Conditional operator - returns b if a is different from zero, returns c 
if a is equal to 0; if a is unknown or floating, the result is the same 
as b A c (bitwise b XOR c). 



2. 14 Vector and array addressing 

« 

A multi-bit net or variable (vector) can be addressed globally — as usual — or par- 
tially. To address a single bit the following syntax is used: 



name [bit] 



For example, the variable rl is declared having an 8 -bit size, like this: 



reg [7:0] r 1 ; 

To access the third bit (rl 2 ) the notation rl [2] might be used. The index that repre- 
sents the selected bit might be a constant or an expression with variables or constants 
(care must be taken to avoid to select a bit position that does not exists). Also a range 
might be selected with the following syntax: 



name [ msb : Isb ] 



For example, to select the bit-range rl 5 2 the notation rl [5 : 2] should be used. The 
values for msb and Isb must be constant, or constant expressions. It is possible to use 
a variable index to select a bit range, with the following syntax: 



Introduction to Verilog 



59 



name [ Isb + : size ] 



For example, as above, to select the bit-range rl 5 2 the notation rl [2+ : 4] could be 
used, but this time, the value for Isb can be an expression with variables, whereas the 
size must be constant (or a constant expression). 

To access an array element, the notation used is just the same as the bit selection for 
vectored nets or variables: 



name [element] 



For example, there might be a static memory of 256 bytes, defined like this: 



reg [7:0] ml[255:0]; 

To access the byte at address 123 the notation ml [123] might be used. Ranges of ar- 
ray elements are not available, but the bits inside a selected element are reachable, like 
explained above. For example, to select the bit ml [123] 3 , the notation ml [123] [3] 
might be used. 

2.15 Strings 

Strings are numbers for Verilog and are represented as bit vectors, where each char- 
acter is placed in a different bit octet. The following example declares a reg variable 
big enough to hold the string "Hello!": 



reg [8*6-1:0] str; 
begin 

str = "Hello ! "; 
end 



60 



Introduction to Verilog 



When the variable str is assigned, it contains exactly the value 48656C6C6F21i 6 . If 
the receiving variable is bigger than the required space, it is padded just like a numeric 
value, on the left! 

reg [8*8-1:0] str; 
begin 

str = "Hello ! "; 
end 



In the above example, the variable str is assigned and then it contains the value 
000048656C6C6F21i 6 . The same way, assigning an empty string to a variable is just 
the same as assigning 0. 

2.16 Functions 

« 

Verilog includes the ability to define functions in a similar way to the C language. 
There are two alternative syntaxes: 



function [automatic^ [range _or_type^ function _name ; 
input [size] input _j?ort; 



begin 

statement ; 

function _name = value ; 

end 



Introduction to Verilog 



61 



function [automatic] [range _or_type] function_name (input [size] input jort [ 
, -]); 
begin 

statement ; 

function jtame = value ; 

end 

Verilog functions should be used in expressions, as they return a value. The value 
returned by a function is of the type specified by the range _or_type , which is a range 
in the form of [msb : Isb ] or a variable type with implicit range (like integer). The 
Verilog functions do not have a 'return' statement, instead they must assign a value to 
a variable with the same name as the function, at the end of it (like the syntaxes above 
show). The Verilog functions can have only input ports as arguments. 

Normal Verilog functions are implicitly 'static', which means that the local variables 
are unique and shared with all concurrent calls: if two threads call the same function, 
it is difficult to predict the result. To make functions work like in C, where local vari- 
ables are implicitly 'automatic' (because they are created inside a stack), the keyword 
automatic must be added to the function declaration. The automatic keyword 
means that each function call creates a private instance of the whole function. 



Figure 2.50. Full adder. 



Ci 

V 



A> 



B 





S = A © B © Ci 



Co = A-B +((AeB) • Ci) 



62 



Introduction to Verilog 



The above figure shows the common circuit of a full adder, where for each output the 
logic expression is reported. The following functions reproduce the same calculations: 



function S 


(input A, input B, input Ci); 


begin 




S = A A 


B A Ci; 


end 





function Co (input A, input B, input Ci) ; 
begin 

Co = A&B + ( (A A B) & Ci) ; 

end 

Functions are used as a way to simplify expressions, through a sequential process that 
cannot contain explicit delays. 

2.17 Netlist modules: combinational circuits 

A netlist module is made of components connected only with nets, without variables. 
Assignments inside this kind of modules are called continuous, because they just 
update continuously and can be defined when declaring the net or separately with the 
assign statement. The following examples show two alternative way for denning a 
continuous assignment to the net wl : 



wire wl = 


a + b; 




wire wl; 
assign wl 


= a + b; 



The following figure shows a full adder netlist module that is to be written in Verilog 
code: all the connections and gates are named. 



Introduction to Verilog 
Figure 2.55. Full adder. 



63 



Ci 

V 



ADD 



A> 



B > 



wl 




g3 



g4 



w3 



w4 



g5 



Co 



To build the above example in Verilog, as a netlist module, can be used primitives or 
assignments, in various ways. The following code example shows the use of primitive 
instantiation without assigning a particular name to the gates that they represent: 



module ADD 


(S, 


Co, A, B, Ci); 


output S 


, Co 




input A, 


B, 


Ci; 


wire wl, 


w3 , 


w4; 


xor (wl, 


A, 


B) ; 


xor (S, 


wl , 


Ci) ; 


and (w3, 


wl , 


Ci) ; 


and (w4, 


A, 


B) ; 


or (Co, 


w3 , 


w4) ; 


endmodule 







The primitive instances can be declared with a name: 



64 



Introduction to Verilog 



module ADD (S, Co, A, B, Ci) ; 

output S, Co; 

input A, B, Ci; 

wire wl, w3, w4; 

xor gl (wl, A, B) ; 

xor g2 (S, wl, Ci) ; 

and g3 (w3, wl, Ci) ; 

and g4 (w4, A, B) ; 

or g5 (Co, w3, w4 ) ; 
endmodule 

Instead of the primitives, a continuous assignment can be used: 



module ADD 


(S, Co, 


A, B, Ci); 


output S, 


Co; 




input A, 


B, Ci; 




wire wl, 


w3, w4 ; 




assign wl 


— A A 


B; 


assign S 


= wl A 


Ci; 


assign w3 


= wl & 


Ci; 


assign w4 


= A & 


B; 


assign Co 


= w3 


w4; 


endmodule 







The continuous assignment can be defined with the wire and port declarations: 



module ADD (S, Co, A, B, Ci) ; 

output S = wl A Ci; 

output Co = w3 | w4 ; 

input A, B, Ci; 

wire wl = A A B; 

wire w3 = wl & Ci; 

wire w4 = A & B; 
endmodule 



Even functions might be used: 



Introduction to Verilog 



65 



module ADD (S, Co, A, B, Ci) ; 
output S, Co; 
input A, B, Ci; 

function sum (input A, input B, input Ci) ; 

begin 

s _ A a B a ci; 

end 

function carry (input A, input B, input Ci) ; 
begin 

Co = A & B + ( (A A B) & Ci) ; 
end 

assign S = sum (A, B, Ci) ; 
assign Co = carry (A, B, Ci) ; 

endmodule 



module ADD (S, Co, A, B, Ci) ; 
output S = sum (A, B, Ci) ; 
output Co = carry (A, B, Ci) ; 

input A, B, Ci; 

function sum (input A, input B, input Ci) ; 
begin 

S = A A B A Ci; 
end 

function carry (input A, input B, input Ci) ; 
begin 

Co = A & B + ( (A A B) & Ci) ; 
end 

endmodule 

The same examples can be made adding delays: 



66 



Introduction to Verilog 



module ADD 


(S, 


Co, 


A, 


B, Ci); 


output S 


, Co 


r 






input A, 


B, 


Ci; 






wire wl, 


w3 , 


w4; 






xor #(8) 


(wl 


, A, 


B) ; 




xor #(8) 


(S, 


wl , 


Ci) 


} 


and #(6) 


(w3 


, wl 


, Ci); 


and #(6) 


(w4 


, A, 


B) ; 




or #(6) 


(Co, 


w3 , 


w4) 


} 


endmodule 












module ADD 


(S, 


Co, 


A, 


B, Ci); 


output S 


, Co 


r 






input A, 


B, 


Ci; 






wire wl, 


w3 , 


w4; 






xor #(8) 


gl 


(wl, 


A, 


B) ; 


xor #(8) 


g2 


(S, 


wl , 


Ci) ; 


and #(6) 


g3 


(w3, 


wl , 


Ci) ; 


and #(6) 


g4 


(w4, 


A, 


B) ; 


or #(6) 


g5 (Co, 


w3 , 


w4) ; 


endmodule 











module ADD (S, Co, A, B, Ci) ; 

output S, Co; 

input A, B, Ci; 

wire wl, w3, w4 ; 

assign #(8) wl — A A B; 

assign #(8) S = wl A Ci; 

assign #(6) w3 = wl & Ci; 

assign #(6) w4 = A & B; 

assign #(6) Co = w3 | w4 ; 
endmodule 



Introduction to Verilog 



67 



module ADD 


(S, 


Co, 


A, B, Ci); 


output S 


= #8 wl 


A Ci; 


output Co 


— 


#6 w3 


1 w4; 


input A, 


B, 


Ci; 




wire wl = 


#6 


A A 


B; 


wire w3 = 


#6 


wl & 


Ci; 


wire w4 = 


#6 


A & 


B; 


endmodule 









module ADD (S, Co, A, B, Ci) ; 
output S, Co; 
input A, B, Ci; 

function sum (input A, input B, input Ci) ; 
begin 

S = A A B A Ci; 
end 

function carry (input A, input B, input Ci) ; 
begin 

Co = A & B + ( (A A B) & Ci) ; 
end 

assign #16 S = sum (A, B, Ci) ; 
assign #14 Co = carry (A, B, Ci) ; 
endmodule 



68 



Introduction to Verilog 



module ADD (S, Co, A, B, Ci) ; 

output S = #16 sum (A, B, Ci); 
output Co = #14 carry (A, B, Ci); 
input A, B, Ci; 

function sum (input A, input B, input Ci) ; 
begin 

S = A A B A Ci; 
end 

function carry (input A, input B, input Ci) ; 
begin 

Co = A & B + ( (A A B) & Ci) ; 
end 
endmodule 

2.18 Behavioral modules 

The module description can contain two types of code block: initial or always. 
These blocks of code describe a sequence of operations, like it happens in the C lan- 
guage, but each block declared inside the module corresponds to a different thread. 
The initial blocks are executed only once, whereas the always blocks are exe- 
cuted repeatedly in a never ending loop. Inside a module there might be any number 
of initial and always blocks. The sequential code that is contained inside these 
blocks is delimited by the keywords begin and end, because the curly brackets are 
used as operators. 



module ADD (S, Co, A, 


B, Ci); 


output reg S, Co; 




input A, B, Ci; 




always 




begin 




S=A+B+Ci; 




Co — ~ (A A B A 


Ci) ; 


end 




endmodule 





The above example transforms the netlist examples of the previous section in the form 



Introduction to Verilog 



69 



of a behavioral module. In this case, it is first calculated the sum of the inputs and then 
the carry out, but as there are no delays, it all happens simultaneously. Please notice 
that the output ports are now changed into a reg type, because inside the behavioral 
blocks the assignments need to modify a reg type destination. 

2.19 Procedural assignments 

The assignments inside the procedural blocks (behavioral) are known as procedural 
assignments, as they differ from the continuous assignments used outside blocks. 
The procedural assignments require to have a reg type variable on the left side of the 
assignment, whereas the continuous assignments require a net type destination. 

There are two types of procedural assignments: blocking and non-blocking. Blocking 
assignments appear and work like the C language assignments. The adjective 'block- 
ing' means that the assignment must be done before the next sentences are executed. 

Inside the following example — which already appeared in a previous section — there 
are two blocking assignments: they just mean that first the sum is assigned to the 
output variable S and then that the carry out is assigned to the output variable Co . 



module ADD (S, Co, A, 


B, Ci); 


output reg S, Co; 




input A, B, Ci; 




always 




begin 




S = A + B + Ci; 




Co = ~ (A A B A 


Ci) ; 


end 




endmodule 





Non-blocking assignments are similar to the blocking ones, but they are executed in 
a separate thread. The following example does the same work as the previous one, but 
the assignments just happens simultaneously: 



70 



Introduction to Verilog 



module ADD (S, Co, A, B, Ci) ; 
output reg S, Co; 
input A, B, Ci; 
always 
begin 

S <= A + B + Ci; 
Co <= ~ (A A B A Ci) ; 
end 
endmodule 

Assignments can be delayed, using the following syntax, for blocking and non- 
blocking assignments: 



dst = [# delay ] expression 



dst <= [# delay ] expression 



The following example is a modified version of the blocking assignment one, shown 
above, adding a 14 time units delay before the sum is calculated: 

module ADD (S, Co, A, B, Ci) ; 
output reg S, Co; 
input A, B, Ci; 
always 
begin 

S = #14 A + B + Ci; 
Co = ~ (A A B A Ci) ; 
end 
endmodule 

In the above example, the value for Co is calculated only after the assignment for 
S, so the output variables are updated at the same time, with the same delay. The 
following example uses non-blocking assignments and it has a different behaviour, 



Introduction to Verilog 

because the two assignments are independent each other: 



71 



module ADD (S, Co, A, B, Ci) ; 
output reg S, Co; 
input A, B, Ci; 
always 
begin 

S <= #14 A + B + Ci; 
Co <= #12 ~ (A A B A Ci) ; 
end 
endmodule 

In the above example, the second assignment does not wait for the first one and the 
delay is less than the first one. This means that the Co output variable is update before 
the S variable. 

2.20 Blocking delays 

« 

The execution of each statement inside a procedural block can be delayed, placing a 
delay number before the statement itself: 



# delay [ procedural jstatement^ ; 



Please notice that the delayed statement is optional, so that the delay can be alone, like 
an autonomous statement. The following example shows a variation of the delayed 
blocking assignments, with the delay specified before the assignment statement: 



module ADD (S, Co, A, 


B, Ci); 


output reg S, Co; 




input A, B, Ci; 




always 




begin 




#14 S = A + B 


+ Ci; 


Co — ~ (A A B A 


Ci) ; 


end 




endmodule 





72 

Please notice that 



Introduction to Verilog 



#14 S = A + B + Ci; 
is just the same as 



#14; 

S = A + B + Ci; 

When non-blocking assignments are used, care must be taken using the blocking as- 
signments; for example, 



S <= #14 A + B + Ci; 

Co <= #12 ~ (A A B A Ci) ; 

is much different from the following: 



#14 S <= A + B + Ci; 

#12 Co <= ~ (A A B A Ci) ; 

The last example above just means: wait 14 time units, then assign the sum to S 
(without waiting), then wait another 12 time units, then assign the carry out to Co 
(without waiting). In fact, the carry out is assigned after 26 time unit. 

2.21 Wait for a level event 

Inside a procedural block it is possible to wait for a value being available in a net or 
variable data type: this is called level event. The wait statement is used to test a level 
event: 



wait ( expression ) \ statement 



Introduction to Verilog 



73 



wait ( expression ) 

[begin 

statement 

end] 



The following example should implement a D latch: 

module latch_d (Q, _Q, D, Clk) ; 
input D, Clk; 
output reg Q, _Q; 
always 
begin 

wait (Clk == 1) 
begin 

#10 Q = D; 
_Q = ~D; 
end 

end 
endmodule 

The above example just waits for the Clk input to be 1, then it updates the outputs 
(with a 10 time units delay); if the Clk is already at the 1 level, the outputs keep 
updating. The statement (or the group of statements) that follows the wait condition, 
might be omitted, if there is only the need to wait for the level event: 



74 



Introduction to Verilog 



module latch_d (Q, _Q, D, Clk) ; 
input D, Clk; 
output reg Q, _Q; 
always 
begin 

wait (Clk == 1) ; 
#10 Q = D; 
_Q = ~D; 
end 
endmodule 

2.22 Wait for an event expressions 

The following syntax is used to wait until an event condition is true (triggered). Please 
notice that the event condition is different from the level condition used by the wait 
statement. 



@ ( event ^expression) [statement^ 



@ ( event ^expression ) 

[begin 

statement 

end] 



The event expression is different from common expressions, because it is meant to be 
true when a specified event occur. 



Introduction to Verilog 75 



Table 2.80. Basic event expressions. 



Expression 


Description 


a 


When the a net or variable changes value, an event occurs. 


posedge a 


When the a net or variable changes value becoming 1 (positive edge). 


negedge a 


When the a net or variable chanses value becomins 0 (negative 
edge). 


el or e2 


When any of the two events (el or el) becomes true. 



The following example should implement a D flip-flop triggered by a positive edge 
clock signal. Please notice that the always statement is followed by the @ statement, 
which owns the begin-end block. 



module ff_d (Q, _Q, 


D, Clk) ; 


input D, Clk; 




output reg Q, _Q; 




always @ (posedge 


Clk) 


begin 




Q = #10 D; 




_Q = ~Q; 




end 




endmodule 





The same thing could also be done using the @ statement just to wait time, blocking 
the procedure flow until the event occurs: 



76 



Introduction to Verilog 



module ff_d (Q, _Q, D, Clk) ; 
input D, Clk; 
output reg Q, _Q; 
always 
begin 

@ (posedge Clk) ; 
Q = #10 D; 

_Q = ~Q; 
end 
endmodule 

2.23 Event variables 

Event variables are only able to store the triggering of an event, with the -> operator: 



begin 

-> e; 
end 

An event can be risen inside an event variable only in a procedural context, as the 
above example might suggest. An event variable can be used as an event expression 
or subexpression: 



@ (e) 

2.24 System tasks and functions 

Verilog provides some special functions for the simulation purpose, to be used inside 
procedural blocks, characterized by the $ (dollar) prefix, useful mainly for debug- 
ging. The most important of these functions is $display () , which allows to show 
some text (to the simulation output console) in a similar way to print f () for the C 
language. 



Introduction to Verilog 



77 



module 




reg [7:0] x, y , z ; 




initial 




begin 




w = 8'h41; 


// A 


x = 8 ' hab; 




y = 8 ' hcd; 




z = 8'hef; 




$display ("Hello: 


w = %c, x = %d, y = 0x%h, z = %b", 


w, x, y, 


z) ; 


end 




endmodule 





The above example should display the following text on the simulation console: 



Hello: w = A, x = 171, y = Oxcd, z = 11101111 



Table 2.87. Common system functions. 


System function 


Description 


$display (string [, x~\ •••) 


It displays on the simulation console the 
string, expanding the metavariables %- 
with the value provided by the nets and 
variables that forms the following argu- 
ments. It works like the print f () func- 
tion for the C language, except that it is 
displayed with a new-line at the end. 



78 



Introduction to Verilog 



System function 


Description 


$monitor (string, x [ , j] •••) 


Continuous monitoring: whenever one 
of the arguments following the string 
changes value, the string is displayed 
on the simulation console, expanding the 
metavariables % ... with the value provided 
by the nets and variables that forms the 
following arguments. It works like the 
printf () function for the C language, 
except that it is displayed with a new-line 
at the end Generallv this function is used 
only on initial blocks, because once re- 
quested, it remains active. 


$t ime 


It returns a value corresponding to the cur- 
rent time, which is expressed in the unit 
specified with the "timescale directive. 
The time value can be assigned to a time 
vanaoie lype ana can oe snown inside 
$ display ( ) or similar functions with the 
metavariable %t. 


$f inish 


It stops the simulation. 



2.25 Control structures 

Inside a procedural block, many of the common C language control structures can 
be used. However it must be recalled that the group of statements is made in Ver- 
ilog language with the keywords begin-end, because the curly brackets are used as 
operators. 



Introduction to Verilog 

Syntax 2.88. Conditional statement: if. 



79 



i f ( condition ) 

statement ; 
[else 

statement; ] 

Syntax 2.89. Selection statement: case. 



case 



casez 



c a s e x ( expression ) 



case _expression : statement ; 

[default: statement ; ] 

endcase 



The selection statement requires some explanations. The first thing that should be 
noticed is that the value in parentheses — that should be compared with the case list 
below — is an expression, which is evaluated at run time. The same is for the case 
conditions appearing below, which are expressions evaluated at run time. Then, after 
each case condition there is only one statement and there is no 'break' keyword (the 
single statement might be expanded with the keywords begin-end). 

There are three type of case statements: case matches the expression in parentheses 
exactly, even the floating and unknown values (z and x) should be the same; casez 
considers that floating values are don't-care values (a don't-care bit value always 
match); casex considers that floating and unknown are don't-care values. 



80 



Introduction to Verilog 



Syntax 2.90. Loop statement: while. 



wh i 1 e ( condition ) 
statement ; 



Syntax 2.91. Loop statement: for. 



for (initialization; condition; statement) 
statement ; 

The following example shows a typical use of the for loop; please notice that the i 
variable is declared as integer type: 

module 

reg [7:0] m[ 1023:0]; 
integer i; 

always 
begin 



for (i = 0; i<1024; i = i + 1) 
begin 

end 



end 



endmodule 



Introduction to Verilog 

Syntax 2.93. Loop statement: repeat. 



81 



repeat (count) 
statement ; 



The repeat loop executes the statement (or the group of statements) a fixed number 
of time, as defined by the count expression. If the count expression has an invalid 
value, it is treated as zero. 

Syntax 2.94. Loop statement: forever. 



forever 

statement ; 



The forever loop executes the statement (or the group of statements) indefinitely 
and the statements after the structure would never be executed. 

2.26 Thread control 

« 

Every procedure inside an initial or always block has a different thread, but inside 
a procedure a group of threads that should be synchronized can be declared with a 
special block called fork- join. 



fork 

statement ; 
statement ; 

join 



The statements inside the fork- join block are started simultaneously, but before 
leaving the block it is ensured that all these statements have completed their work. 



82 



Introduction to Verilog 



If instead of a single statement a begin-end group is placed, the contained statements 
are executed sequentially in a single thread. 

1 Identifiers might also contain other escaped characters, but this possibility should 
be avoided and it is not taken into account inside the chapter. 

2 Please notice that the syntax is simplified and it does not consider the signedness, 
because the chapter takes into account only the unsigned representation. 

3 The value 232i 0 is equal to IIIOIOOO2, but allowing only seven bits, the value is 
truncated to 1101000 2 that is equal to 104i 0 . 



Chapter 



Combinational circuits 

3.1 Decoder 87 

3.2 Demultiplexer 90 

3.3 Multiplexer 93 

3.4 Multiplexer and demultiplexer with paralel I/O 96 

3.5 Binary encoder 99 

3.6 Priority encoder 102 

3.7 Logic units 106 

3.8 Shift and rotation 107 

3.9 Addition 114 

3.10 Subtraction 119 

3.11 Addition and subtraction together 123 

3.12 Carry lookahead 125 

3.13 2' s complement 132 

3.14 Multiplication 133 

3.15 Division 142 

3.16 Magnitude comparator 145 



2' s complement 132 adder 114 arithmetic shift 107 binary encoder 99 carry 
lookahead 125 combinational circuit 83 combinational network 83 data distributor 
90 data selector 93 decoder 87 demultiplexer 90 demux 90 encoder 99 fast adder 125 
full-adder 114 half-adder 114 half-subtractor 119 logic shift 107 logic unit 106 
multiplexer 93 priority encoder 102 ripple-carry 114 rotation 107 shift 107 
subtraction 119 two's complement 132 



A combinational circuit, otherwise known as combinational network, is a system of 
logic gates conveniently connected together, organized with a set of input ports and a 
set of output ports, where the output logic values are directly and univocally defined 



84 



Combinational circuits 



from the input logic ones. The overall combinational circuit can be represented as a 
box with input and output ports, together with a truth table that describes the output 
values based on the input combinations. 



input 



combinational 
circuit 



output 



The figure above shows a combinational circuit example with five input ports and 
three output ports, but the proportion between input and output ports depends on the 
function that should be performed by the circuit, or rather from the purpose that the 
circuit should satisfy. 



Please notice that a combinational circuit is not influenced by the time variable 
and even by the power-on random variable; therefore, inside these circuits, the 
propagation delay is a problem that is not taken much into consideration, because, 
after a certain delay from the input change, the output is updated as specified by 
the truth table. 



The simpler combinational circuits are those that have only one output port, which 
are better known as logic gates. 

Figure 3.2. Combinational circuits with a single output port. 



n input 




one output 



To understand better the matter, it can be noticed that a circuit composed only by 
a single input port and a single output port can be made in four different ways, as 
evidenced by the following figure. 



Combinational circuits 

Figure 3.3. Truth table about four functions of a single variable. 



85 



one input 



input types distinguished on the output values 



A 



► one output 



0 

1 



/o 


/. 


f 2 


f 3 


0 


1 


0 


1 


0 


0 


1 


1 




1 

A 

A 

NO" 

A — 

As it can be seen on the annotations inside the above figure, the circuit corresponding 
to the fi function is the inverter (NOT), whereas the one corresponding to the f 2 
function is the buffer (not-inverter). 

A combinational circuit with two input ports and a single output can have 16 al- 
ternative functions, as it can be seen in the following figure, where the functions 
corresponding to the common logic ports are evidenced. 



86 



Combinational circuits 



Figure 3.4. Truth table about sixteen functions of two variables. 



input 

A B 



-<>- 



0 
0 



0 

1 

0 

1 



types distinguished on the output values 
fo f\ fi f\ J 5 fe fi f% fio fll f\2 ftf fl4 f\5 



0 
0 
0 
0 



1 

0 
0 
0 



0 

1 

0 
0 



1 0 

1 0 

0 1 

0 0 



1 

0 

1 

0 



0 

1 
1 

0 



1 
1 
1 

0 



0 
0 
0 

1 



1 

0 
0 

1 



0 

1 

0 

1 



1 
1 

0 

1 



0 
0 

1 
1 



1 0 

0 1 

1 1 
1 1 



1 
1 




Combinational circuits 



87 



3.1 Decoder 

The decoder is a combinational circuit that, for every input combination, asserts only 
one output port. Precisely, for every input combination there is only one output port 
to assert. Therefore, for n input ports there are 2" output ports. Usually, this kind of 
combinational circuit has also an additional input control port that should be asserted 
to enable the output. 

Figure 3.5. Block diagram of a decoder with four output ports (2-to-4). The two 
input selection ports are labeled as A 0 and Aj (address); the input control port is 
labeled as E (enable); the output ports are labeled from Y 0 to Y 3 . The drawing on 
the right is more compact and the input selection ports are grouped together. 



« 



address 



enable 



-*■ 


AO 




YO 


-► 


-► 


A1 


decoder 


Y1 


-► 








Y2 


-► 




E 




Y3 


-► 






+ 







AO, A1 2 



o 

CD 
"D 




Y0..Y3 



Table 3.6. Truth table for a decoder with four output ports, from Y 0 to Y 3 ; two 
selection input ports, A 0 and Aj; one enable input port E. 



E 


A, 


A 0 


Y 3 


Y 2 




Y 0 


0 


X 


X 


0 


0 


0 


0 


1 


0 


0 


0 


0 


0 


1 


1 


0 


1 


0 


0 


1 


0 


1 


1 


0 


0 


1 


0 


0 


1 


1 


1 


1 


0 


0 


0 



88 



Combinational circuits 



Figure 3.7. Two examples of implementation of a decoder with four output ports: 
the two selection ports are labeled A 0 and Ai, the enable port is labeled E and 
the output ports are labeled from Y 0 to Y 3 . 



A1 



A0> 
A1> 



E> 



> 



YO 



-o 



> 



-Of 



> 



> 



> Y1 
Y2 

> Y3 



A1 > 
AO- 



AO 



> 



YO 



> 



Y1 



> 



> Y2 



J > Y3 



A 
E 



Listing 3.8. Example with Verilog. 



module decoder_2_to_ 


4 (Y, A, E); 


input [1:0] 


A; 




input E; 






output [3:0] Y; 




// 






function [3 


:0] f2to4 (input [1:0] A, input E) ; 


if (E == 


1) 




begin 






case 


(A) 




0 : 


f2to4 = 


4'b00 01; 


1 : 


f2to4 = 


4'b0010; 


2 : 


f2to4 = 


4'b0100; 


3 : 


f2to4 = 


4'bl0 00; 


endcase 




end 






else 






begin 






f2to4 


= 4'b00 00; 


end 






endf unction 







Combinational circuits 



89 



// 

assign #8 Y = f 2to4 (A, E) ; 
endmodule 



Listing 3.9. Verilog gate level alternative code following the picture 3.7 on the 
left. 



ILLU UU1 c UcLUUcI L D 


A. 1 Y 


A 


& ) r 


input [1:0] A; 








input E; 








output [3:0] Y; 








assign Y[0] = E & 


~A[1] 


& 


~A[0] ; 


assign Y [ 1 ] = E & 


~A[1] 


& 


A[0] ; 


assign Y [2 ] = E & 


A[l] 


& 


-A[0] ; 


assign Y[3] = E & 


A[l] 


& 


A[0] ; 


endmodule 









Listing 3.10. Verilog gate level alternative code following the picture 3.7 on the 
right. 



module decoder_2_ 


to. 


_4 (Y, 


A, 


E) ; 


input [1:0] A; 










input E; 










output [3:0] Y; 










wire [1:0] _A; 










assign _A = ~A; 










assign Y [ 0 ] = E 


& 


_A[1] 


& 


_A[0] ; 


assign Y [ 1 ] = E 


& 


_A[1] 


& 


A[0] ; 


assign Y [2 ] = E 


& 


A[l] 


& 


_A[0] ; 


assign Y [ 3 ] = E 


& 


A[l] 


& 


A[0] ; 


endmodule 











90 



Combinational circuits 



« 



3.2 Demultiplexer 

The demultiplexer (demux), known also as data distributor, is a combinational circuit 
that works like a decoder with an additional input port switched to the selected output. 

Figure 3.11. Block diagram of a demultiplexer with four output ports. The two 
selection input ports are labeled A 0 and Aj, the data input corresponds to the 
variable D, the enable input is E, the output ports are labeled from Y 0 to Y 3 . The 
drawing on the right is more compact and the input selection ports are grouped 
together. 



address 



data 



enable 



AO 




Y0 


A1 


demux 


Y1 


D 

E 




Y2 
Y3 




t 



AO, Al 




Y0..Y3 



The difference between the decoder and the demultiplexer should be clear from the 
figure above: the Y n output port selected has the same value read at the D input (unless 
the enable port is negated). 

Table 3.12. Truth table for a demultiplexer with four output ports, from Y 0 to Y 3 ; 
two selection input ports, A 0 and Ai \ a data input S; an enable input E. 



E 


Aj 


A 0 


D 


Y 3 


Y 2 


Yi 


Y 0 


0 


X 


X 


d 


0 


0 


0 


0 


1 


0 


0 


d 


0 


0 


0 


d 


1 


0 


1 


d 


0 


0 


d 


0 


1 


1 


0 


d 


0 


d 


0 


0 


1 


1 


1 


d 


d 


0 


0 


0 



Combinational circuits 



91 



Figure 3.13. Two examples of implementation of a demultiplexer with four output 
ports: the two selection ports are labeled A 0 and Ai, the data to be switched to 
the selected output is read from the input D, the enable port is labeled E and the 
output ports are labeled from Y 0 to Y 3 . 



A1 



A0>" 



A1 >- 



D> 



-Or 



E> 



-o 



"Or 



> 



> 



YO 



Y1 



Y2 



Y3 



A1 >- 
A0>- 



Tl 



AO 



> 



YO 



3 > Y1 

3 > Y2 



J > Y3 



A A 
D E 



It should be noticed that D and E work just like alternative enabling inputs, so the 
truth table might be simplified as it appears below. 

Table 3.14. Alternative way to represent the truth table of the demultiplexer with 
four outputs. Please notice that here the data and enable inputs are both at the 
beginning. 



E 


D 


Aj 


A 0 


Ys 


Y 2 


Yi 


Y 0 


0 


X 


X 


X 


0 


0 


0 


0 


X 


0 


X 


X 


0 


0 


0 


0 


1 


1 


0 


0 


0 


0 


0 


1 


1 


1 


0 


1 


0 


0 


1 


0 


1 


1 


1 


0 


0 


1 


0 


0 


1 


1 


1 


1 


1 


0 


0 


0 



Listing 3.15. Example with Verilog. 



module demultiplexer_2_to_4 (Y, A, D, E) ; 
input [1:0] A; 
input D, E; 
output [3:0] Y; 
// 



92 



Combinational circuits 



function [3 


:0] f2to4 (input [1:0] A, input D, input E) ; 


if (e == 


1 n == i) 


bpai n 




case 


(A) 




f?to4 = 4'b0001- 


1 : 


f2to4 = 4'b0010; 


2 : 


f2to4 = 4'b0100; 


3 : 


f2to4 = 4'bl000; 


endcase 


end 




else 




begin 




f2to4 


= 4'b00 00; 


end 




endf unction 




// 




assign #8 Y 


= f2to4 (A, D, E) ; 


endmodule 





Listing 3.16. Verilog gate level alternative code following the picture 3.13 on the 
left. 



module demult iplexer_2_ 


to_4 (Y, 


A, D, E); 


input [1:0] A; 








input E, D; 








output [3:0] Y; 








assign Y [ 0 ] = E 


& D & 


~A[1] & 


~A [ 0 ] ; 


assign Y [ 1 ] = E 


& D & 


~A[1] & 


A [ 0 ] ; 


assign Y [2 ] = E 


& D & 


A[l] & 


~A [ 0 ] ; 


assign Y [ 3 ] = E 


& D & 


A[l] & 


A [ 0 ] ; 


endmodule 









Combinational circuits 



93 



Listing 3.17. Verilog gate level alternative code following the picture 3.7 on the 
right. 



module demult iplexer_2_to_4 (Y, A, D, E) ; 

input [1:0] A; 

input E, D; 

output [3:0] Y; 

wire [1:0] _A; 

assign _A = ~A; 

assign Y[0] = E & D & _A[1] 

assign Y[l] = E & D & _A[1] 

assign Y[2] = E & D & 

assign Y[3] = E & D & 
endmodule 



& 
& 



A[0] 
A[0] 



A[l] & _A[0] 
A[l] & A[0] 



A demultiplexer can be obtained from a decoder (provided that it has the enable input 
port), likewise a demultiplexer can be reduced to work as a decoder. 

Figure 3.18. On the left a decoder is adapted to work as a demultiplexer; on the 
right a demultiplexer is adapted to work as a decoder. 



D 



AO 
A1 



decoder 



Y0 
Y1 
Y2 
Y3 





AO 




-► 


YO 




-► 


A1 

demux 


Y1 






D 

E 


Y2 




-► 


Y3 



Common demultiplexer integrated circuits are 74154, 74138, 74139 and 74238 (see 
section uO.l). 

3.3 Multiplexer 

The multiplexer (mux), or data selector, is a combinational circuit that selects the 
value of a single input port and reproduces that value to the output port. The input 
port chosen depends on the value of a group of selection ports (or address ports). For 
n selection ports there can be 2" input ports. 



« 



94 



Combinational circuits 



Figure 3.19. Block diagram of a multiplexer with four input ports. The two se- 
lection inputs are labeled A 0 and Ai, the data input ports are labeled from D 0 
to D 3 , the enable input is E, the output is Y . On the right it is shown a compact 
representation where the selection variables are joined together in a multiple line. 



address or selection 



input ports to choose from 



enable 



■+ 


AO 


Y 


-¥ 


A1 




-*■ 


DO 


mux 






D1 






D2 




-► 


D3 






E 








t 



output corresponding to 
the input, from DO to D3 



AO, A1 yL. 



D0..D3 



Y 



Table 3.20. Truth table for a multiplexer with four data inputs, from D 0 to D 3 ; 
two selection inputs, from A 0 to Aj; an enable input, E; one output, Y. 



E 


Aj 


A 0 


D 3 


D 2 


Dj 


Do 


Y 


0 


X 


X 


d 3 


d 2 


di 


d 0 


0 


1 


0 


0 


d 3 


d 2 


di 


d 0 


d 0 


1 


0 


1 


d 3 


d 2 


di 


d 0 


di 


1 


1 


0 


d 3 


d 2 


di 


d 0 


d 2 


1 


1 


1 


d 3 


d 2 


di 


d 0 


d 3 



Figure 3.21. Two example of a multiplexer with four data inputs. 

A0> 



A0>- 
A1>- 



D0>- 
D1>- 
D2>- 
D3>- 



E>- 



A1 >- 



> 



D0>- 
D1 > 
D2>- 
D3>- 



E>- 



y 
y 



Combinational circuits 95 



Listing 3.22. Example with Verilog. 



module multiplexer 1 


of 4 (Y, 


A, 


D, E) ; 


inrmt r 1 • 0 1 A; 

— 1— J. 1 Kj' L-L L- |_ -1_ • L/ J JTX f 








incut r 3 • 0 1 D ; 








input E; 








output Y; 








// 








function flof4 (input [1:0] 


A 


i nnnt" T^'Dl D i nnnt" F. ^ * 

_l_ 1 1 k-* LA L-. |_ • V_/ J J—/ ^ _l_ 1 1 ' U. L- J — I / ^ 


if (e — 1 ) 








r~\ q rT n in 








^ o c~\ ( 7\ \ 
Ldbc inj 








n . -F1 r^-F A — 
U . 11014 — 


n rni • 






1 • f 1 of 4 = 


n r 1 i • 

u L -L J t 






? • f 1 of 4 = 


u L ^ J i 






1 • f 1 of 4 = 


n r 3 1 • 






endcase 








end 








else 








begin 








flof4 = 0; 








end 








endf unction 








// 








assign #8 Y = flof4 


(A, D, 


E) ; 




endmodule 









Listing 3.23. Verilog gate level alternative code following the picture 3.21 on the 
left. 



module mult 


iplexer_ 


_l_of_4 (Y, A, D, E) ; 


input [ 1 : 


0] A; 




input [3: 


0] D; 




input E; 






output Y; 






wire wO, 


wl, w2, 


w3 ; 



96 



Combinational circuits 



assi cr n 

* *- • > ► > —i— j. ± 


#4 


wO = 


= E & 


~a r o l 


& 


~a n i 


& 


D f 0 1 ; 


ass icrn 


#4 


wl = 


= E & 


a r oi 


& 


~a r 1 1 


& 


Dm ; 


crn 

k_J k_J _!_ 1 1 


#4 


w2 - 


= E & 


~a r o l 

n L u J 


& 


Am 


& 


D T 2 1 ; 


ass ign 


#4 


w3 z 


= E & 


A[0] 

L J 


& 


A [1] 


& 


D [ 3 ] ; 


assign 


#4 


Y ~- 


= wO | 


wl | 


w2 


1 w3 ; 






endmodule 



















Listing 3.24. Verilog gate level alternative code following the picture 3.21 on the 
right. 



module mu 


It 


iplexe 


r_ 


1_ 


of_4 


(Y, 


A, D, 




E) ; 


input [ 


1 : 


0] A; 
















input [ 


3 : 


0] D; 
















input E 




















output 


Y; 


















wire [1 


: 0 


] _A; 
















wire wO 


r 


wl , w2 




w3 


} 










assign 


_A 


= ~A; 
















assign 


#4 


wO = 


E 


& 


_A[0] 


& 


_A[1] 


& 


D[0] ; 


assign 


#4 


wl = 


E 


& 


A[0] 


& 


_A[1] 


& 


D[l] ; 


assign 


#4 


w2 = 


E 


& 


_A[0] 


& 


A[l] 


& 


D[2] ; 


assign 


#4 


w3 = 


E 


& 


A[0] 


& 


A[l] 


& 


D[3] ; 


assign 


#4 


Y = 


wO 




wl | 


w2 


1 w3; 






endmodule 





















Common multiplexer integrated circuits are 74150, 74151 and 74157 (see section 
u0.2). 

3.4 Multiplexer and demultiplexer with paralel I/O 

Multiplexers and demultiplexer might be required to work on data composed of more 
than a single bit. In that case, many multiplexers or demultiplexers are required, but 
joining the selection and enabling ports. The following figures show a demultiplexer 
and a multiplexer in a detailed version (on the left) and in a compact version with 
some wires grouped together (on the right). 



Combinational circuits 



97 



Figure 3.25. Demultiplexer with input and outputs composed of four value vec- 
tors. 



AO, A1 



DO, D1, D2, D3 



^3 



Y0,0 Y0,1 Y0,2 Y0,3 



-J- Y1 ,0 Y1 ,1 Y1 ,2 Y1 ,3 



-/■ Y2,0 Y2,1 Y2,2 Y2,3 



A -v 



Y3,0 Y3,1 Y3,2 Y3,3 



D 



4 



CD 



1 0 \ 

— A~ 
—4- 



Y0 
Y1 
Y2 
Y3 



Figure 3.26. Multiplexer with inputs and output composed of four value vectors. 



AO, A1 



D0,0 D0,1 D0,2 D0,3 



D1,0 D1,1 D1,2 D1,3 



D2,0 D2,1 D2,2 D2,3 



D3,0 D3,1 D3,2 D3,3 



Y0 Y1 Y2 Y3 



A' 



2 



DO 

Dl ^ 

D2 -t^- 

D3 



0 



7^ Y 



98 



Combinational circuits 



Listing 3.27. Quad 2-to-4 demultiplexer example in Verilog. 

module demult iplexer_2_to_4_x4 (YO, Yl, Y2, Y3, A, D, E) ; 
input [1:0] A; 
input E; 
input [3:0] D; 

output [3:0] YO, Yl, Y2, Y3; 
wire [1:0] _A; 
assign _A = ~A; 

assign #8 YO = (E & _A [ 1 ] & _A[0])?D:0; 
assign #8 Yl = (E & _A [ 1 ] & A[0])?D:0; 
assign #8 Y2 = (E & A[l] & _A[0])?D:0; 
assign #8 Y3 = (E & A[l] & A[0])?D:0; 
endmodule 



Listing 3.28. Quad l-of-4 multiplexer example in Verilog. 

module mult iplexer_l_of_4_x4 (Y, A, DO, Dl, D2, D3, E) ; 
input [1:0] A; 
input [3:0] DO, Dl, D2, D3; 
input E; 
output [3:0] Y; 
wire [1:0] _A; 
wire [3:0] wO, wl, w2, w3; 
assign _A = ~A; 

assign #4 wO = (E & _A [ 0 ] & _A [ 1 ] ) ?D0 : 0 ; 

assign #4 wl = (E & A[0] & _A [ 1 ] ) ?D1 : 0 ; 

assign #4 w2 = (E & _A [ 0 ] & A[1])?D2:0; 

assign #4 w3 = (E & A[0] & A[1])?D3:0; 

assign #4 Y = wO | wl | w2 | w3; 
endmodule 



Combinational circuits 



99 



3.5 Binary encoder 

A binary encoder is a combinational circuit having n output lines and 2" input lines, 
where only an input line at a time can be asserted and the value obtained from the 
output reports the number of the asserted input line. The following examples show 
binary encoders with n equal to 1, 2 and 3. 

Table 3.29. Truth table for a binary encoder with two inputs and one output. 





Do 


Yo 


0 


1 


0 


1 


0 


1 



Figure 3.30. To obtain a binary encoder with two input lines it is enough to con- 
nect the second input line to the output. 

DO > 



D1 > >~ YO 

Table 3.3 1. Truth table for a binary encoder with four input and two output ports. 



D 3 


D 2 




Do 


Yj 


Yo 


0 


0 


0 


1 


0 


0 


0 


0 


1 


0 


0 


1 


0 


1 


0 


0 


1 


0 


1 


0 


0 


0 


1 


1 



100 



Combinational circuits 



Figure 3.32. Binary encoder with four input and two output ports. The first input 
line is not connected, because if it is asserted the output should be zero anyway. 

D0> 



D1 >- 



^ YO 



D2> 



D3>- 



> Y1 



Table 3.33. Truth table for a binary encoder with eight input and three output 
ports. 



D 7 


D 6 


D 5 


D 4 


D 3 


D 2 




Do 


Y 2 


Yi 


Yo 


0 


0 


0 


0 


0 


0 


0 


1 


0 


0 


0 


0 


0 


0 


0 


0 


0 


1 


0 


0 


0 


1 


0 


0 


0 


0 


0 


1 


0 


0 


0 


1 


0 


0 


0 


0 


0 


1 


0 


0 


0 


0 


1 


1 


0 


0 


0 


1 


0 


0 


0 


0 


1 


0 


0 


0 


0 


1 


0 


0 


0 


0 


0 


1 


0 


1 


0 


1 


0 


0 


0 


0 


0 


0 


1 


1 


0 


1 


0 


0 


0 


0 


0 


0 


0 


1 


1 


1 



Combinational circuits 101 

Figure 3.34. Binary encoder with eight input and three output ports. 
D0> 



D1 > 



D2> 



D3> 



D4> 



D5> 



D6> 



> Y0 



> Y1 



> Y2 



D7> 

Listing 3.35. Binary encoder example, with eight input and three output ports, 
written in Verilog. This solution is different from the picture 3.34, because if the 
input value is not as expected, the encoded output is zero. 



module bi 


nary_ 


.encoder (Y 


, D) ; 


input [ 


7:0] 


D; 






output 


[2:0] 


Y; 






// 










f unct io 


n [2 : 


0] be£ 


3to3 


(input [7:0] D) ; 


case 


(D) 








1 


: be8 


to3 = 


0; 





102 



Combinational circuits 



z : 


be 


btOJ 


= 1 


4 : 


be 


T j_ „ O 


= 2 


8 : 


be 


3to3 


= 3 


1 6 : 


be 


3to3 


= 4 


32 : 


be 


3to3 


= 5 


64 : 


be 


3to3 


= 6 


128 : 


be 


3to3 


= 7 


default 


: bet 


3to3 



endcase 
endf unction 
// 

assign #6 Y = be8to3 (D) ; 
endmodule 



Listing 3.36. Binary encoder example describing the gates in picture 3.34. 



module binary_encoder (Y, 


D) ; 






input [7:0] D; 








output [2:0] Y; 








assign #6 Y[0] = D[l] | 


D[3] 


1 D[5] 


1 D[7]; 


assign #6 Y[l] = D[2] | 


D[3] 


1 D[6] 


1 D[7]; 


assign #6 Y[2] = D[4] | 


D[5] 


1 D[6] 


1 D[7]; 


endmodule 









3.6 Priority encoder 

The priority encoder is a binary encoder that allows the assertion of every input line, 
giving on the output the number corresponding to the asserted input having priority 
above all the others. In that case it is also allowed to have no input line asserted, thus 
there might be an additional output port that is asserted only when there is at least an 
input line asserted. 



Combinational circuits 



103 



Table 3.37. Truth table for a priority encoder with four input ports. The asserted 
input with the lower index has priority above the other, therefore the letter 'X' 
is used to show an unspecified value for the other lower priority input ports. The 
output port GS (group select) is asserted when at least an input line is asserted. 









Do 


GS 




Yn 


0 


0 


0 


0 


0 


X 


X 


X 


X 


X 


1 


1 


0 


0 


X 


X 


1 


0 


1 


0 


1 


X 


1 


0 


0 


1 


1 


0 


1 


0 


0 


0 


1 


1 


1 



Figure 3.38. Priority encoder with four input ports. 

priority 

DO 



D1> 



D2>- 



D3> 



encoding 



2 > 



> 



> Y0 



Y1 



^ GS 



104 



Combinational circuits 



Figure 3.39. A different way to obtain the same priority encoder with four input 
ports. 



D0>- 



D1>" 



D2>" 



D3>" 



> 



> 



> 



> Y0 



> Y1 



> GS 



Listing 3.40. Example with Verilog. 



module priority_ 


encoder 


_4_to_2 (Y, 


GS, D) ; 


input [3: 


0] D; 








output [1 


: 0] Y 








output GS 


r 








// 










f unct ion 


[1:0] 


f4to2 


( input [3:0] 


D) ; 


if (D & 


1) 








f 4to2 


= 0; 








else if 


(D & 


2) 






f 4to2 


= i; 








else if 


(D & 


4) 






f 4to2 


= 2; 








else if 


(D & 


8) 






f 4to2 


= 3; 








else 










f 4to2 


= 0; 








endf unct ion 








// 










assign #8 


Y = 


f 4to2 


(D) ; 




assign #8 


GS = 


D[0] | 


D[l] I D[2] 


1 D[3]; 



Combinational circuits 



105 



endmodule 



Listing 3.41. Verilog gate level alternative code following the picture 3.38. 



module priority_encoder 


_4_to_2 


(Y, GS, 


D) ; 


input [3:0] D; 










output [1:0] Y; 










output GS; 










wire wO, wl, w2 


r 








assign #4 wO = 


~D[0] 


& D[l] ; 






assign #4 wl = 


~D[0] 


& ~D[1] 


& D[2] ; 




assign #4 w2 = 


~D[0] 


& ~D[1] 


& ~D[2] 


& D[3] ; 


assign #4 Y[0] 


= wO 


1 w2; 






assign #4 Y[l] 


= wl 


1 w2; 






assign #8 GS = 


D[0] I 


D[l] I 


D[2] | 


D[3] ; 


endmodule 











Listing 3.42. Verilog gate level alternative code following the picture 3.39. 



module priority_encoder 


_4_to_2 


(Y, GS, 


D) ; 


input [3:0] D; 








output [1:0] Y; 








output GS; 








wire [2:0] _D; 








wire wO, wl, w2 ; 








assign _D = ~D; 








assign #4 wO = _D [ 0 ] 


& D[l] ; 






assign #4 wl = _D [ 0 ] 


& _D[1] 


& D[2] ; 




assign #4 w2 = _D [ 0 ] 


& _D[1] 


& _D[2] 


& D[3] ; 


assign #4 Y[0] = wO 


1 w2; 






assign #4 Y[l] = wl 


1 w2; 






assign #8 GS = D[0] | 


D[l] I 


D[2] | 


D[3] ; 


endmodule 









A common priority encoder circuit is 74148 (see i 1.3.1). 



106 



Combinational circuits 



3.7 Logic units 



« 



Using a multiplexer it is possible to obtain easily a logic unit, able to do the common 
logic operations, selecting the desired one through a selection value. For example, it 
might be possible to build the circuit that does the task shown in the following figure: 



2 





f 


A 






logic L 


B 





fj f output 

0 0 A AND B 

0 1 A OR B 

1 0 A XOR B 
1 1 NOT B 



Figure 3.44. Logic unit implementation example with four options. 

2 



f>- 



"7^ 




> L 



Logic units like this one are useful if the input lines (A and B) are multi-bit sized. To 
obtain this it suffice to place in parallel more single-bit units with the function control 
input if) connected together. 



Combinational circuits 



107 



Figure 3.45. More logic units can be connected in paralel, to operate on multi-bit 
values. The diagram on the right is a compact representation of the same circuit. 

f 



A0..A3 

' 4 



B0..B3 

4 





A B 

logic f 

L 



A B 

logic f 

L 



f>- 







/ 






■ 

/ 




/ 






/, 
/ 




4 

/ 




— » 


/ 


1 


/ 





-> L 



f f 

1 0 



output 



L0..L3 



0 0 A AND B 

0 1 A ORB 

1 0 A XOR B 
1 1 NOT B 



3.8 Shift and rotation 

The bit shift is an important binary operation that can be implemented with a com- 
binational circuit. There is an ordered group of n inputs, starting from 0 to n-1, a 
group of n outputs ordered in the same way and there might be a carry input and a 
carry output. Often it is considered the shift of a single binary digit, because more bi- 
nary digits might be shifted repeating the operation. The shift and rotation operations 
require to specify the direction: left or right. 

The easiest kind of shift is the logic shift, which moves the bits left or right, losing 
the most significant bit or the least significant one, inserting a zero at the opposite 
side. The following figures implements the logic shift and the other types of shifts 
and rotations, using multiplexers, where the connection to the ground means a fixed 
0 input. 

1110 original value 1110 original value 



« 



110 0 left logic shift 



0 111 right logic shift 



108 



Combinational circuits 



Figure 3.47. 4-digit left and right logic shift, with 2-input multiplexers. The shift 
direction is established by the value received by the / input. The shift loses a 
binary digit from one side and gets a zero from the opposite side. 



D 

v 



f 

V 





' A 


/ 





CD CM i- O 



0 



0 



1 0 



1 0 



i " i f=0: shift left of a single digit 

f-1: shift right of a single digit 

I 

S 

Listing 3.48. 4-digit logic shift: example with Verilog. 



module logic_shif t_4 


(S, D, 


f) ; 


input [3:0] D; 






input f; 






output [3:0] S; 






// 






function [3:0] lsh 


( input 


[3:0] D, input f ) ; 


if (f == 0) 






lsh = D << 1; 






else 






lsh = D >> 1; 






endf unction 






// 







Combinational circuits 



109 



assign #6 S = lsh (D, f ) ; 
endmodule 



The other Verilog examples of the section describe only the gate logic level, assuming 
that the 2-input multiplexers are implemented as the following figure shows: 



Listing 3.50. 4-digit logic shift: detailed gate level implementation. 



module logic_shift_ 


.4 (S, D, f); 






input [3:0] D; 








input f; 








output [3:0] S; 








wire _f = ~f; 








// 








assign #6 S[0] = 


(D[l] & f) ; 






assign #6 S [ 1 ] = 


( (D[2] & f) I 


(D[0] 


& _f ) ) ; 


assign #6 S [ 2 ] = 


( (D[3] & f ) I 


(D[l] 


& _f) ) ; 


assign #6 S [ 3 ] = 


(D[2] & _f) ; 






endmodule 









The arithmetic shift is made in the same way as the logic one, with the exception 
that the right shift must keep the sign unaltered. In practice, when doing an arithmetic 
right shift, the digit inserted on the most significant position is the same as the original 
one. This kind of shift is called 'arithmetic' because the result is the same as the 



D1 

V 



DO 

V 





Y 



110 



Combinational circuits 



multiplication and division by two. However it should be noticed that the left shift 
might produce an overflow, corresponding to the lost of the original sign. 



1110 original value 

110 0 left arithmetic shift 

0 110 original value 

110 0 left arithmetic shift (*) 

10 10 original value 

0 10 0 left arithmetic shift (*) 



1110 original value 

1 1 1 1 right arithmetic shift 

0 110 original value 

0 0 11 right arithmetic shift 

0 110 original value 

0 0 11 right arithmetic shift 



(*) when shifting to the left, a sign inversion might be produced (overflow) 

Figure 3.52. 4-digit, left and right arithmetic shift, using 2-input multiplexers. 
The shift direction is defined by the value received by the / input. 



D 

v 



f 

V 





'4 


/ 





m (M t- o 



0 



1 0 



1 0 



1 0 



1 0 



Q M O 

I I 



f=0: left shift of a single binary digit 
f=l: right shift of a single binary digit 



Combinational circuits 111 



Listing 3.53. 4-digit arithmetic shift: detailed gate level implementation. 



module arithmetic 


.shif t_4 


(S, D, 


f ) ; 






i nnnt r ? • n i n • 

_L 1 L^~J U.L- [ J . U J U f 












1 riDl ] t" f I 












outrmt r 3 • 0 1 S • 












T A T "j TO f = ~ "F • 
VV J L J_ J— j 
























assian #6 S \ 0 1 = 


: (D r 1 1 


& f ) • 








assicrn #6 ST] 1 = 


: ( (d r 2 1 


& f ) 1 


(d r oi 


& 


f ) ) ; 


assign #6 S [ 2 ] = 


: ((D[3] 


& f) 1 


(D[l] 


& 


_f) ) ; 


assign #6 S [ 3 ] = 


: ((D[3] 


& f) 1 


(D[2] 


& 


_f) ) ; 


endmodule 













The rotation is a shift operation where the binary digit lost from one side is inserted 
on the opposite side, either on the left or the right rotation. 

1110 original value 



1110 original value 
110 1 left rotation 



0 111 right rotation 



0 110 original value 
110 0 left rotation 



0 110 original value 
0 0 11 right rotation 



10 10 original value 
0 10 1 left rotation 



10 10 original value 
0 10 1 right rotation 



112 



Combinational circuits 



Figure 3.55. 4-digit rotation, with 2-input multiplexers. The rotation direction is 
specified by the value received by the input /. 



1 0 / 



1 0 L 



D 

v 





'4 


/ 





f) CM t- O 



1 0 L 



f 

v 



1 0 



f=0: left rotation of a single digit 
f-1: right rotation of a single digit 

V 



s 

Listing 3.56. 4-digit rotation: detailed gate level implementation. 



module rotation_4 


(S, D, 


f) ; 










input [3:0] D; 














input f; 














output [3:0] S; 














wire _f = ~f ; 














// 














assign #6 S[0] = 


= ((D[l] 


& 


f ) 


(D[3] 


& 


_f) ) ; 


assign #6 S [ 1 ] = 


= ((D[2] 


& 


f ) 


(D[0] 


& 


_f) ) ; 


assign #6 S [ 2 ] = 


= ((D[3] 


& 


f ) 


(D[l] 


& 


_f) ) ; 


assign #6 S [ 3 ] = 


= ((D[0] 


& 


f ) 


(D[2] 


& 


_f) ) ; 


endmodule 















Combinational circuits 



113 



The rotation with carry uses the previous carry for the digit inserted on one side and 
saves the removed digit from the opposite side as the new value for the carry (after 
the rotation). 

.1 110 original value .... 1 original carry 



\ \ 10 1 left rotation 



1 final carry 



1110 ... original value 
1^1 1 1 right rotation 



1 . original carry 



0 



final carry 



Figure 3.58. 4-digit input, rotation with carry, using 2-input multiplexers. The 
rotation direction is specified by the value received by the / input. 



V 

Co 



0 



D 

v 





X 4 


/ 





Ci 

v 



CO OJ -i- o 



f 

V 



0 



0 



0 



Q M -» O 
I I 



V 



f=0: left rotation of a single digit 
f=l: right rotation of a single digit 



114 



Combinational circuits 



« 



3.9 Addition 

The binary addition, made in the same common way used for the decimal number- 
ing system, does not generate a carry higher than 1. It can be verified through the 
following table. 

Table 3.59. Binary addition. 



first 

ii i 

addend 


second 

ii i 

addend 


previous carry 
(carry in) 


generated 
carry 

(carry out) 


result 


0 


0 


0 


0 


0 


0 


0 


1 


0 


1 


0 


1 


0 


0 


1 


0 


1 


1 


1 


0 


1 


0 


0 


0 


1 


1 


0 


1 


1 


0 


1 


1 


0 


1 


0 


1 


1 


1 


1 


1 



Therefore, the combinational circuit that can do the binary addition must have three 
input (first addend, second addend, carry in) and two output ports (result, carry out). 



Figure 3.60. Adder block diagram. The abbreviation FA stands for full-adder. 
FA: full-adder 

previous carry (carry in) 

A B 





addends 






k + 






A B 






Co FA Ci 

S 










1+ 






generated carry (carry out) sum 

It is custom to consider the full-adder (the one shown above) to be made of two 
smaller modules, known as half-adders. The half- adder is a combinational circuit 
with two input ports, corresponding to the two addends, and two output ports, cor- 
responding to the sum and the generated carry; in practice, the half-adder has no 
previous carry. 



Combinational circuits 



115 



Table 3.61. Truth table for a half-adder: A and B are the addends, S and Co are 
the sum and the output carry. 



A 


B 


Co 


s 


0 


0 


0 


0 


0 


1 


0 


1 


1 


0 


0 


1 


1 


1 


1 


0 



It can be easily guessed that the half-adder sum can be obtained with an XOR gate 
and that the output carry requires an AND gate. 

Figure 3.62. Half-adder block diagram and implementation example. The abbre- 
viation HA stands for half-adder. 











A 


B 




Co 


HA 








S 











A> 
B> 



> S 
Co 



To obtain a full-adder from half-adders, it is necessary to sum also the input carry. 
Figure 3.63. Full-adder block diagram, obtained with two half-adders. 

Ci> 

' ' > s 



A> 
B> 



B 



HA S 
Co 




O >Co 



> S 



116 



Combinational circuits 



Figure 3.64. Full-adder alternative implementations, with the help of Karnaugh 
maps. 



A 


B 


Ci 


Co 


s 


0 


0 


0 


0 


0 


0 


0 


1 


0 


1 


0 


1 


0 


0 


1 


0 


1 


1 


1 


0 


1 


0 


0 


0 


1 


1 


0 


1 


1 


0 


1 


1 


0 


1 


0 


1 


1 


1 


1 


1 




C() = AB+BCi+ACi 



*-BCi 



AB 



► ACi 



AB 

AB 

AB 
AB 



Ci 



Ci 



0 



S = A©BffiCi 
ABCi 



->■ ABCi 



ABCi 



^ ABCi 



A> 
B> 

Ci> 



> S 



Co 



To be useful, the addition should be applied to binary addends composed of more than 
a single digit, therefore it is necessary to assemble in paralel some adders, passing 
properly the carry from the less significant digit to the more significant one, digit by 
digit. This method of carry propagation is known as ripple-carry and is illustrated by 
the following figure. 



Combinational circuits 



117 



Figure 3.65. Ripple-carry 4-digit adder. On the right is shown a compact repre- 
sentation, but it is not specified there in what way the carry is propagated. 



A 

V 
/ 



B 

V 



Ci 

V 



CO CM t- O 



CO CM t- O 



A B 




A B 






A B 






A B 




Co FA Ci 




Co FA 


Ci 




Co FA 


Ci 




Co FA ci 




•<- *■ 


«- 4- 




<- 


S 




S 






S 






S 





A 



Co 



+ 

s 



B 



Ci 



co ro -Mo 



V V 
Co S 

The described adder works correctly with the addition of positive and negative num- 
bers, when the negative numbers are represented as 2's complement of the positive 
equivalent value. 

Listing 3.66. A simple Verilog implementation of a 4-bit adder. 



module adder_4 (Co, S, A, B, Ci); 
input [3:0] A, B; 
input Ci; 
output Co; 
output [3:0] S; 
// 

assign #30 {Co, S} = A + B + Ci; 
endmodule 



118 Combinational circuits 



Listing 3.67. Gate level implementation of a 4-bit adder with ripple-carry. 



module adder_4 (Co, 


S, A, B, Ci) ; 




input [3: 


0] A, 


R • 
a t 






input Ci; 










output 


Co 


r 








output 


[3 


: 0] S 


r 






wire [4 


:0] C; 








// 












f unct ion 


add (input A, input B, input Ci) ; 


add = 


A 


A B A Ci 


r 






endf unct ion 








// 












f unct ion 


carry 


(input A, input B, 


"i nmit" f" 1 "!^ * 


carry 




A&B | 


A&Ci | B&Ci; 




endf unct ion 








// 












assign 


#0 


C[0] 




Ci; 




assign 


#6 


C[l] 




carry (A[0], B[0] 


. c r 0 1 ) ; 

r ^ L w J / t 


assign 


#6 


C[2] 




carry (A[l], B[l] 


, C [ 1 ] ) ; 


assign 


#6 


C[3] 




carry (A[2], B[2] 


, C[2] ) ; 


assign 


#6 


C[4] 




carry (A[3], B[3] 


, C[3]); 


// 












assign 


#5 


S[0] 




add (A[0], B[0], 


C[0] ) ; 


assign 


#5 


S[l] 




add (A[l], B[l], 


C[l] ) ; 


assign 


#5 


S[2] 




add (A[2], B[2], 


C[2] ) ; 


assign 


#5 


S[3] 




add (A[3], B[3], 


C[3] ) ; 


// 












assign 


#0 


Co = 


C [ 4 ] ; 




endmodule 













Combinational circuits 



119 



3.10 Subtraction 

« 

The basic building block for the subtraction is the half-subtr actor : As the order of 
the operands is significant, it is necessary to distinguish between minuend and sub- 
trahend, therefore all the following examples will use this notation: D=M-S. 

Table 3.68. Half-subtractor truth table. 



M 


s 


B 0 


D 


0 


0 


0 


0 


0 


1 


1 


1 


1 


0 


0 


1 


1 


1 


0 


0 



Figure 3.69. Half-subtractor. 

HS: half-subtractor 



difference 

5> D 

> Bo 

subtrahend borrow 

Instead of the output carry there is the borrow (output borrow) that is asserted when 
the subtrahend is greater than the minuend. The full-subtractor has another input, 
which is the input borrow coming from a previous digit. To build the full-subtractor it 
is possible to use two half- subtrac tors, where the second one subtracts from the result 
of the first one the input borrow. 



minuend 



M 



S> 




-o 



120 



Combinational circuits 



Table 3.70. Full-subtractor truth table. 



M 


s 


Bi 


Bo 


D 


o 


o 


o 


o 


o 


o 


o 

V./ 


1 


1 


1 


o 


1 


n 

V/ 


1 


1 


o 


1 


1 


1 


o 


1 


0 


0 


0 


1 


1 


0 


1 


0 


0 


1 


1 


0 


0 


0 


1 


1 


1 


1 


1 



Figure 3.71. Full-subtractor. 

FS: full-subtractor 



M>" 

s>- 



M 



HS 

Bo 



Bi> 

borrow in 



M 



HS 

Bo 



-5- D 



o 



> Bo 

borrow out 




Bi 



Figure 3.72. Full-subtractor alternative implementation, with the help of Kar- 
naugh maps. 



M 


s 


Bi 


Bo 


D 


0 


0 


0 


0 


0 


0 


0 


1 


1 


1 


0 


1 


0 


1 


1 


0 


1 


1 


1 


0 


1 


0 


0 


0 


1 


1 


0 


1 


0 


0 


1 


1 


0 


0 


0 


1 


1 


1 


1 


1 



Bi 



Bi 



Bo = M Bi + MS+SBi 



MS 

MS 

MS 
MS 



0 


l 




— >■ 


c 

1 

V 






— >■ 


rn 

V 






— *- 


0 


1 

^ J 






0 


0 





^ M Bi 



MS 



SBi 



MS 

MS 

MS 
MS 



Bi Bi D= MffiSffiBi 

-►M S Bi 



0 



0 



0 

1 



-►MSBi 



-►M S Bi 



-►M S Bi 



Combinational circuits 



M> 
S> 

Bi> 




D 



-C 



-C 



Bo 



As for the addition, it is possible to build a chain of full- subtracter. 
Figure 3.73. 4-bit subtraction. 



M 

V 



/ 



s 

V 
/ 



Bi 

V 



I I 

CO CM t- o 



I I 

CO CM t- O 



M S 




M S 


Bo FS Bi 




Bo FS Bi 


4- 4- 


D 




D 



CO M -> O 

I I 





M S 




M S 




Bo FS Bi 




Bo FS Bi 


4-4- 


4-*- 




D 




D 



M 



Bo 



"X/ 



/a 



D 



v 

Bo 



V 



122 



Combinational circuits 



Listing 3.74. A simple Verilog implementation of a 4-bit subtractor. 



module subtractor 


_4 (Bo, D, M, S, Bi) ; 


incut [3*01 M, 


S ; 


i ttdi ] t" Ri : 




out 1^1 ] 1" Rn : 




outDut [3*01 D ; 




// 




assign #30 {Bo, 


D} = M - S - Bi; 


endmodule 





Listing 3.75. Gate level implementation of a 4-bit subtractor. 



module subtractor_ 


4 (Bo, D, M, S, 


Bi) ; 


input 


[3: 


0] M, S 


} 




input 


Bi; 








output 


Bo 


r 






output 


[3 


:0] D; 






wire [4:0] B; 






// 










f unct ion 


sub (input M, input S, 


input Bi) ; 


sub 


= M 


A S A Bi; 






endf unct ion 






// 










f unct ion 


borrow 


(input M, input 


S, input Bi ) ; 


borrow 


= ~M&Bi 


| S&Bi | -M&S; 




endf unct ion 






// 










assign 


#0 


B[0] = 


Bi; 




assign 


#6 


B[l] = 


borrow (M[0] , 


S[0] , B[0] ) ; 


assign 


#6 


B[2] = 


borrow (M [ 1 ] , 


S[l], B[l]); 


assign 


#6 


B[3] = 


borrow (M [ 2 ] , 


S[2], B[2]); 


assign 


#6 


B[4] = 


borrow (M [ 3 ] , 


S[3], B[3]); 


// 










assign 


#5 


D[0] = 


sub (M[0], S[0], B[0]); 


assign 


#5 


D[l] = 


sub (M[l], S[l], B[l]); 



Combinational circuits 



123 



assign #5 


D [2] 


= sub 


(MT21 , 


S [2 ] , 


B [2 ] ) ; 




d r 3 1 


— sub 


(m r 3 1 , 


s r 3 1 . 


B T 3 1 ) ; 


// 












assign #0 


Bo = 


B [ 4 ] ; 








endmodule 













3. 1 1 Addition and subtraction together 

The full-adder works correctly for the sum of positive and negative numbers, when 
the negative ones are represented by the 2's complement method, therefore, to trans- 
form an adder into a subtractor, it is enough to calculate the 2's complement for the 
subtrahend. To achieve the result it is more convenient to invert all the subtrahend 
bits (l's complement) and also the input carry, which now assumes the role of in- 
put borrow. To obtain coherently an output borrow, even the output carry should be 
inverted. 

Figure 3.76. 4-digit subtractor: in that case it is calculated A -B. On the right side 
it is shown a compact representation of the same thing. 



« 




A B 




A B 




A B 




A B 




Co FA Ci 




Co FA Ci 




Co FA Ci 




Co FA Ci 




4- 4- 


4- 4- 


4- 4- 




s 




s 




s 




s 





co ro — t o 

I I 



V 



Bo 



V 



Bo 



A B Bl 

X 



+ 



/a 



s 



The addition and subtraction can be combined with XOR gates, instead of inverters, 



124 Combinational circuits 

with an additional function control input, which specify the action to take. 
Figure 3.77. 4-digit addition or subtraction. 



A 

V 

X- 



I I 

CO OJ i- o 



B 

V 

X 



f 

V 



Ci/Bi 

V 



I I 

CO C\J i — O 



Co/Bo 



co ro — 1 o 
I I 



A 



Ci/Bi 



0 





A B 




A B 




A B 




A B 




Co FA Ci 

s 




Co FA Ci 

s 




Co FA Ci 

s 




Co FA Ci 
S 


•4- 


4- «- 


«- 4- 


«-«- 



+ 
s 





X 4 


/ 





\ 0 



Co/Bo 



V 



i ; ; i 

CO CM t — O 



11' 



nor 



co ro o 
I I 



A 



Listing 3.78. Gate level implementation of a 4-bit adder and subtracter. 

module addsub_4 (CoBo, S, f , A, B, CiBi) ; 
input [3:0] A, B; 
input f, CiBi; 
output CoBo; 
output [3:0] S; 
wire [4:0] C; 
// 

function add (input A, input B, input C) ; 

add = A03 A C; 
endf unction 
// 

function carry (input A, input B, input C) ; 

carry = A&B|A&C|B&C; 
endf unction 
// 



Combinational circuits 



125 



assign 


ff U 


P r n 1 


— Lidi r ; 






as s ign 


44- r 
ff b 


p r 1 I 

C L 1 J 


= carry (A[0] 


n r n 1 A 


r , C L U J ) 


assign 


#6 


^ r o i 

C [2] 


= carry (A[l] 


n r 1 1 A 

f B [1] 


f , C [1] ) 


ass ign 


44- C 

ff b 


L L -3 J 


= carry ( A [ 2 ] 


n r o l a 

t B L 2 J 


t, C [ 2 J ) 


as s ign 


ff b 


C [ 4 ] 


= carry (A[3] 


/ B [ 3 ] 


t, C [ 3 ] ) 


// 












as s ign 


44- C 
ff 0 




— add ( A L u J r 


B L u J r , 


p r n 1 1 . 

C L U J ) ; 


assign 


ii rr 

#5 


S [1] 


i i / tv r 1 ~\ 

= add (A [ 1 ] , 


B [1] A f , 


C [ 1 ] ) ; 


ass ign 


44- R 
ff O 


c r o i 
o L Z J 


— add ( a l z j , 


B l z J r , 


c r o i \ . 


assign 


#5 


S [3] 


= add (A[3] , 


B [3] A f , 


C [ 3 ] ) ; 


// 












assign 


#0 


CoBo 


= C [4] A f ; 







endmodule 



3.12 Carry lookahead 

The addition with a significant quantity of bits, using the ripple-carry method of carry 
propagation is very slow. To accelerate the operation, every digit requires to get a 
valid previous carry in the shortest possible time, with the method known as carry- 
lookahead. In the following expressions, the variables A/, Bi and d represent the 
two addends and the input carry of the stage i (the digit taken into consideration); 
therefore, the carry generated from this stage is represented by the variable C i+1 . 

Figure 3.79. Alternative ways to calculate the output carry. 



A,. 


B, C, 




0 


0 0 


0 


0 


0 1 


0 


0 


1 0 


0 


0 


1 1 


1 


1 


0 0 


0 


1 


0 1 


1 


1 


1 0 


1 


1 


1 1 


1 



c 



AB 

AB 

AB 
AB 



0 
0 


0 

f ■> 

1 








► 


f 

1 

V 


- — ^ 

1 

> 




>~ 


0 


1 / 




► 



AB 

AB 

AB 
AB 



c 


c 


0 


0 


0 


Q 






1 


i 




J 



C(A®B) 



AB 



AB+C(A©B) 



« 



AB+BC+AC 



AB+(A+B)C 

The figure above shows that the carry can be synthesized in various ways, one of 



126 



Combinational circuits 



which uses the XOR operator. Two equivalent expressions are chosen from the above 
picture: 

C<+i = AiBi+(Ai+Bi)Ci = AiBi+(Ai®Bi)Ci 

From these expressions, two new variables are defined, G; and P t , which stand for 
generation and propagation, so that the carry Cm is defined by the value of G„ Pi 
and d. 

— Gi+PiCi 

It is obvious that G; is equivalent to A*/?*, whereas P< can be considered either equal to 
Af+fi,- or to Ai@Bi. If the first generated carry (C 7 ) can be obtained as Ci=G 0 +PoC 0 , 
the second one is obtained as C 2 =Gi+Pi(Go+C 0 Po), and the same way all the subse- 
quent ones can be determined. The solutions for the first four carries follow: 



Ci 


— Go+PoCo 


C 2 


= Gi+PiCi 


c 2 


= G f i+Pi(G f 0 +P 0 C f o) 


c 2 


= Gi+PiGq+PiPqCq 




= G2+P2C2 


c 3 


= G 2 +P 2 (G 1 +P 1 Go+PiPoCo) 


c 3 


= G2+P2Gi+P2PlGo+i : 2PlPoC f o 


c 4 


= G3+P3C3 


c 4 


= G 3 +P3(G2+P2Gi+P 2 PlGo+P2PlPoC'o) 


c 4 


= G3+P3G2+P3P2G1+P3P2P1G0+P3P2P1P0C0 



To simplify the expressions, P n and G n are defined in the following way: 

Pn = Pn-lPn-lPn-l " ' P\Pq 

G n = G n -i+P n -iG n -2+Pn-2Pn-lG n -3-\ hPn-2Pn-l ' ' ' P\Gq 

Having defined P„ and G„, the carry C n can be defined as: 

C n = G n +P n Co 

The following figure shows a combinational circuit that determines the carries of 
four binary digits, starting from the initial carry and the values from B3..0 and G3..0, 



Combinational circuits 



127 



as described by the equations that defines this relation. The draw contains also the 
logic necessary to determine the value of B 4 and G 4 , which can be useful to connect 
together more modules of this type. 

Figure 3.85. Diagram for the determination of four carries, starting from the ini- 
tial one (Co) and from the values of P, and G l? as described by the logic equations. 

co> 1 



po>- 

G0>- 



P1>- 

G1>- 



P2>- 
G2>- 



P3>- 
G3>- 



C1 = G0+P0-C0 



— > 02 

O- 



G1+PLG0+PLP0-C0 



G2+P2-G1+P2-P1-G0+P2-P1-P0-C0 



D 
3- 



-> C4 = G3+P3-G2+P3-P2-G1+P3-P2-P1-G0+P3-P2-P1-P0-C0 



o- 



^ P4 = P3-P2-PLP0 



G4 = G3+P3-G2+P3-P2-G1+P3-P2-P1-G0 



o- 



The adder that produces the values G and P can be synthesized without the output 



128 



Combinational circuits 



carry, as this value is determined by the above module. There are two alternative 
solutions, because the P value can be defined either as A,- +B t or A,- ®B t . 

Figure 3.86. Addition modules with P and G outputs, but without the output 
carry. 



C> 

B>- 

A>- 



> S 



o- 



> p =A+B 



c>- 

B>- 
A>- 



O 



E> 



> S 

-> p = A®B 



-> G = A-fl 



^ G = A-fl 



The following figure shows a 4-digit adder, made of the previous modules of addition 
and carry-lookahead. 



Combinational circuits 



Figure 3.87. Fast 4-digit adder. 

co> — 



B0>- 
A0>- 



B1>- 
A1>- 



B2> 
A2> 



B3>- 
A3>- 



E)0 ^ so 

o 

o 



PO 



GO 



:)0 — ^ si 



O- 



pi 



G1 



O 

o- 



> S2 

P2 



G2 



=)0— S3 

o 
o 



P3 



G3 



o- 



C1 



C2 



C3 



P4 



G4 



130 



Combinational circuits 



An adder, like the one shown above, can be connected with other modules to increase 
the number of digits, without adding too much delay. In the following figure, the 
module SUM4 corresponds to the one described in figure 3.87, where only the last 
two carries are connected to the outside (the last two carries will be necessary to test 
if there is an overflow); the module CLH4 corresponds to the one described in figure 
3.85, which is used to connect the addition modules. 

Figure 3.88. 20-bit adder, made of 4-bit modules connected together. 



C19 



C20 -^r- 



A 

V 



CD CM CO O 
V. V. ^ N CO 

en in 



4.4 



A 




B 




A 


B 


C3 


SUM4 


CO 




<- 


C3 


SUM4 






<- 






CO 


C4 








f 


C4 




G4 


P4 


S 






G4 


P4 S 



f 



A 


B 


03 SUM4 


CO 


C4 




G4 P4 


S 



f 



/ 4 



/ 4 



B 

V 



CD 



/ 4 



A 


B 






A 




B 


03 SUM4 


CO 


4- 


<- 


C3 


SUM4 


CO 


C4 






f 


C4 






G4 P4 


S 






G4 


P4 


S 



JL 



G3 


P3 


C3 


G2 


P2 


C2 G1 


pi 


C1 


GO 


P0 


C4 




















G4 










CLH4 








CO 


P4 





















-<co 



19:16 



S 



Listing 3.89. Fast 4-digit adder, Verilog gate level implementation. 



module SUM4 (C4, C3, P4, G4, 


s, 


A, B, CO); 


input [3:0] A, B; 






input CO; 






output C3, C4, P4, G4; 






output [3:0] S; 






wire [4:0] C, P, G; 






// 






assign #0 C[0] = CO; 






assign #5 S[0] = A[0] A B[0] 


A C [ 


0] ; 


assign #5 S [1] = A [ 1 ] A B [ 1 ] 


A C [ 


i] ; 



Combinational circuits 



131 



ass ign 


#5 


s r 2 1 


= A[2] 


A B 


;2; 


A c 


r 2 1 


r 






ass ign 


#5 


S [3] 


= A[3] 


A B 


;3] 


A c 


[3] 


f 






// 






















ass ign 


#5 


p r oi 


= a[o; 


1 B 


; 0] 


r 










ass ign 


#5 


p r n 


= ATI" 


1 B 


;i; 


r 










a q s i crn 


#5 


p r 2 1 


- a [ 2 ' 


1 B 


" 2 ' 


r 










ass ign 


#5 


P [3] 


= A[3] 


1 B 


;3] 


f 










ass ign 


#6 


p r 4 1 


= P \3~ 


&P 


;2; 


&p 


rn 


&p r oi 

VJK. J_ |_ \J J 


r 




// 






















ass ign 


#5 


g r oi 


= a[o; 


&B 


;o; 












ass ign 


#5 


G [ 1] 


= A[l] 


&B 


;i; 












ass ign 


#5 


G [21 


= A[2] 


&B 


;2; 


r 










pi Q c; -j prri 


#5 

Tr ' 


g r 3 1 


= a r 3 1 


&B 


" 3 1 


r 










ass ign 


#7 


g r 4 1 


= g [3; 


1 P 

1 


;3; 


&G 


[21 


1 P [31 

1 L ^ J 


&p 


r 2 1 &g rn 








1 P T3" 


&P 


;2; 


&P 


rn 


&G [ 0] 


r 




// 






















ass ign 


#7 




= g [ o; 


1 P 


;o; 


&C 


r oi 








ass ign 


#7 


C [21 


= g rn 


1 P 

1 *~ 


;i; 


&G 


r oi 


i p rn 


&p 


r o l & c r o l ; 


ass ign 


#7 


C [31 


= G [2] 


1 P 

1 


;2; 


&G 


rn 


1 P [21 


&p 


rn &g roi 








1 P [21 

1 L ^ . 


&P 


;i; 


&P 


roi 

L w J 


&C [ 0] 


r 




r s s i crn 


#7 


c r 4 1 

^ L ^ J 


- g r 3 1 


P 


" 3 1 


&G 


r 2 i 


i p r 3i 

1 n L -J J 


Ot J- 


r 2 1 &g r i i 








1 P T3" 


&P 


;2; 


&p 


rn 


&G [ 0 ] 












1 P T3" 


&P 


;2; 


&p 


rn 


&p r oi 

VJC. J_ |_ \J J 


&c 


roi ; 


// 






















ass ign 


#0 


C4 = 


C [ 4 ] ; 
















ass ign 


#0 


C3 = 


C r 3 1 ; 
















assign 


#0 


P4 = 


P [ 4 ] ; 
















assign 


#0 


G4 = 


G [ 4 ] ; 
















endmodule 





















A common 4-bit fast adder circuit is the 7483 (see il.4.1). 



132 



Combinational circuits 



« 



3.13 2's complement 

To change the sign of an integer binary number, it is necessary a circuit that calculates 
the 2's complement. To obtain the 2's complement it is required to calculate the l's 
complement (bit inversion), adding 1. 

Figure 3.90. 2's complement calculation, corresponding to the sign inversion of 
an 4-bit integer number. 

minus 

V 















B A 






4- 


C 


HA 




<<- 






s 








• — o 



B A 






B A 


c HA 






c HA 


s 




s 



->■ o 



OUT 



The example in the above figure shows that the input data is inverted (negated) if 
the input minus is asserted, but the same minus value is added, producing the final 
2's complement. If otherwise the minus input is not asserted, the input data is not 
changed and the output result remains the same. 



Combinational circuits 



133 



3.14 Multiplication 

The binary multiplication is a process that requires the addition and the bit shifting. 
To operate correctly on signed integers, the calculation should be done extending the 
input data to a double bit size; for example, if multiplicand and multiplier have only a 
4-bit size, the result requires a size of up to 8 bits, but the calculation should be done 
as if also the input data were 8-bit wide. See the following examples. 

Figure 3.91. signed and unsigned 4-bit multiplication. 

integer multiplication negative multiplicand, positive multiplicand, negative multiplicand, 

without sign positive multiplier negative multiplier negative multiplier 

OOOOlOllx lllllOllx OOOOOlllx lllllOllx 

00001101 = 00000101 = 1 1 1 11101 = 1 1 1 11101 = 

00001011+ 11111011+ 00000111+ 11111011+ 

00000000+ 00000000+ 00000000+ 00000000+ 

00101100+ 11101100+ 00011100+ 11101100+ 

01011000+ 00000000+ 00111000+ 11011000+ 

00000000+ 00000000+ 01110000+ 10110000+ 

00000000+ 00000000+ 11100000+ 01100000+ 

00000000+ 00000000+ 11000000+ 11000000+ 

00000000= 00000000= 10000000= 10000000= 



« 



10001111 11100111 11101011 00001111 

In the figure above, the first example on the left shows the multiplication of two 
unsigned values, which are extended using 0s on the most significant side, before 
the multiplication is done. The other examples are made with signed values and the 
negative ones are extended with Is on the most significant side, to keep the original 
negative sign, before the operation take place. 

To resolve the problem with a combinational circuit, it is necessary to cross the mul- 
tiplicand and multiplier values, verifying at every useful position the coincidence of 
values equal to 1 . The following two figures should be overlapped, as they show the 
concept in two phases: the outputs from the AND gates must be added vertically to 
generate the product. 



134 



Combinational circuits 



Figure 3.92. Intersection between multiplicand and multiplier, using AND gates. 

multiplicand multiplicator 



cr> OJ j- o 



/4 



Combinational circuits 



135 



Figure 3.93. The value generated by the AND gates is added with full-adders. 



□ 



1 



lr 
□ 




o 



li 



lr 
□ 




1 



lr 

□ 




B A 




B A 




B A 




B A 


Co FA Ci 




Co FA ci 




Co FA ci 




Co FA ci 




+- <- 




s 




s 




s 




s 



lr 
□ 



B A 




B A 




B A 




B A 


Co FA ci 




Co FA ci 




co FA Ci 




Co FA ci 


4- <- 


+- +- 


+- <- 


s 




s 




s 




s 



B A 




B A 




B A 




B A 


Co FA Ci 




Co FA ci 




Co FA ci 




Co FA ci 




<- «- 


4- «- 


s 




s 




s 




s 





1° 



P7 



P6 



P5 



P4 



P3 



P2 



V 
P1 



PO 



To solve the problem in a nice way, it is necessary to build specific cells, using a 
full-adder. As it can be seen in the following figure, one addend receives the product 
calculated by the AND gate, whereas the other addend receives the value from the 
previous row. 



136 



Combinational circuits 



Figure 3.94. Cell used to build the matrix that adds and shifts the multiplicand. 



Bo 



Co 



Ao <: 




So 



Si - sum input 
Ai - A input - multiplicand 
Bi - B input - multiplicator 
Ci - carry in 

So = sum output = ( (Ai AND Bi) + Si + Ci) 

Ao - Ai 

Co = carry out 

Bo = Bi 



The cells of the previous figure should be connected properly together: the following 
figure shows a solution limited to unsigned multiplicand and multiplier. 



Combinational circuits 



137 



Figure 3.95. 4-digit unsigned integer multiplication, producing an 8-digit result: 
P=AxB. 







Si Ai 




Bo 


Bi 

MUL 




Co 


Ci 




AO 


So 



Bo 


Si Ai 






Si 


Ai 


Bi 

MUL 




Bo 


MUL 


Bi 


Co 


Ci 






Co 




Ci 


AO 


So 






AO 


So 





1 



Si 

MUL 

So 





Si 


Ai 


Bo 




Bi 




MUL 


Co 




Ci 


Ao 


So 





Bo 


Si 


Ai 


MUL 


Bi 


Co 




Ci 


AO 


So 





Bo 


Si 


Ai 






Si 


Ai 


MUL 


Bi 


«- 




Bo 


MUL 


Bi 


Co 




Ci 




<- 


Co 




Ci 


Ao 


So 








Ao 


So 





Si 

MUL 

So 



Si 


Ai 


Bo 

MUL 


Bi 


Co 


Ci 


Ao So 





MUL 



Bo 
Co 


Si 


Ai 






Si 


Ai 


MUL 


Bi 




«- 


Bo 


MUL 


Bi 




Ci 




<- 


Co 




Ci 


AO 


So 








Ao 


So 





'n, 



Si 

MUL 

So 



Si Ai 






Si Ai 


Bo Bi 

MUL 

Co Ci 




«- 


Bo 


MUL B ' 






Co 


Ci 


AO So 






AO 


So 



la 



la 



v 

p 

To multiply signed integers, it is necessary an additional control input, used to specify 
if the input data is signed, then the net should be extended as if the multiplicand and 
the multiplicator have a double bit size, extending their values conforming to the 
original sign that they are intended to have. 



138 



Combinational circuits 



Figure 3.96. Full solution (but excessively heavy) to calculate the product of two 
4-bit integers. 



/4 



signed values 



5 



=0, 





Bo 


Si 


Ai 




Bo 


Si 


Ai 




Bo 


Si 


Ai 




Bo 


Si 


Ai 




Bo 


Si 


Ai 




Bo 


Si 


Ai 




Bo 


Si 


Ai 






Bi 






Bi 


«^~'~* 




Bi 






Bi 


^1 — ' *- 




Bi 


*■ 






Bi 








Bi 




Co 


MUL 






Co 


MUL 






Co 


MUL 






Co 


MUL 






Co 


MUL 








Co 


MUL 








Co 


MUL 








Ci 






Ci 






Ci 


~ <- 




Ci 


+ — 1 5^ 




Ci 








Ci 








C 




AO 


So 






AO 


So 






Ao 


So 






Ao 


So 






Ao 


So 








Ao 


So 








Ao 


So 









Si 


Ai 




Bo 


Si 


Ai 




Bo 


Si 


Ai 




Bo 


Si 


Ai 




Bo 


Si 


Ai 




Bo 


Si 


Ai 


• 




Bi 






Bi 






Bi 






Bi 








Bi 








Bi 




Co 


MUL 






Co 


MUL 






Co 


MUL 






Co 


MUL 


Ci 






Co 


MUL 


Ci 






Co 


MUL 








Ci 






Ci 






Ci 


4- *" 




«- 








«- 




C 




AO 


So 






AO 


So 






AO 


So 






AO 


So 








AO 


So 








AO 


So 





•EL 



Si Ai 
B 

MUL 



Co 
Ao So 



Ci 



Bo 


Si 


Ai 


Co 


MUL 


Bi 




u 


AO 


So 





lo 



Si 
MUL 

So 



Si 
MUL 

So 



Si 
MUL 

So 



Si 
MUL 

So 



Si 
MUL 

So 



Si 
MUL 



Si 
MUL 



Si 
MUL 

So 



Si 
MUL 

So 



Si 
MUL 



Si 
MUL 



Si 
MUL 

So 



Si 
MUL 

So 



Bo 
— Co 



Si 
MUL 



Si 
MUL 



Si 
MUL 

So 



Si 
MUL 

So 



Si 
MUL 

So 



MUL 

So 
+ 

A 

Si 

MUL 

So 



MUL 

So 



lo 



-d= 



lo 



■JOlUi-f^LOM-'O 



lo 



signed values 



p 



Combinational circuits 



139 



The sign problem can be resolved changing the sign, before and after the multiplica- 
tion, so that a simple unsigned circuit can be used. In the following figure, the module 
MUL4 is a multiplication circuit that can accept only unsigned values; the modules 
minus4 and minus8 are circuits that can change the sign of the values that they filter, 
if their input minus is asserted. 

Figure 3.97. Signed integer multiplication, using an adapted unsigned multiplier. 



SignecP*" 



[2] 



0 



A 
V 



/a 



[1] 



[1] the most significant bit is read to know the sign of the integer 
[2] multiplicand and multiplier have different signs 



IN 


r. 


IN 


minus 


■* 


minus 


minus4 




minus4 


OUT 




OUT 



MUL4 



minus 

minus8 



OUT 



The figure above shows that from the inputs A and B the most significant bit is used 
to know their signedness; if they are negative, their value is converted into positive, 
before the multiplication. After the multiplication, if the input signs were different, 
the result is converted into a negative value. This sign transformation is enabled by the 
control input Signed, so that unsigned number can be multiplied as well. The mod- 
ule minus4 corresponds to the one shown in the section 3.13, whereas the minus8 
module is an extention working with 8 bits. 

It should be observed that if the result is truncated to the same number of digits than 
the multiplicand and the multiplier, assuming that the result can fit in it and that the 
input data is always signed, then the result is valid, without the need to handle the 



140 



Combinational circuits 



signedness. The following examples try to demonstrate this assertion. 

Figure 3.98. 4-digit binary multiplication, truncating the result at the same size 
as multiplicand and multiplier. 



integer multiplication 
without sign 

lOllx 

1101 = 

1011 + 
0000 + 
1100 + 
1000 = 

1111 

invalid result 
because it is truncated 
too early 



negative multiplicand, 
positive multiplier 

HOlx 

0010 = 
0000 + 
1010 + 
0000 + 
0000 = 

1010 

valid result 



positive multiplicand, 
negative multiplier 

OlOlx 

1110 = 

0000 + 
1010 + 
0100 + 
1000 = 

0110 

valid result 



negative multiplicand, 
negative multiplier 

lOllx 

1101 = 

1011 + 
0000 + 
1100 + 
1000 = 

1111 

valid result 



Combinational circuits 



Figure 3.99. Simplified multiplication combinational circuit with the result trun- 
cated to the same bit size as the multiplicand and multiplier. 



A 

V 



CO CM t — O 



0 



0[ 



0 



Bo 


Si 


Ai 






Si 


Ai 


MUL 


Bi 


«- 


4- 


Bo 


MUL 


Bi 


Co 




Ci 


«- 


«- 


Co 




Ci 


Ao 


So 








Ao 


So 









Si 


Ai 


«- 


Bo 




Bi 






MUL 


<^ 


Co 




Ci 




Ao 


So 





Bo 


Si 


Ai 






Si 


Ai 


MUL 


Bi 


<- 


4- 


Bo 




Bi 


Co 










MUL 






Ci 


4- 


4- 


Co 




Ci 


Ao 


So 








Ao 


So 





Bo 


Si 


Ai 






Si 


Ai 


MUL 


Bi 


4- 


«- 


Bo 


MUL 


Bi 


Co 




Ci 


■»- 


<- 


Co 




Ci 


Ao 


So 








Ao 


So 





Bo 


Si 


Ai 






Si 


Ai 


MUL 


Bi 


4- 


<- 


Bo 


MUL 


Bi 


Co 




Ci 


*- 


4- 


Co 




Ci 


Ao 


So 








Ao 


So 





Bo 


Si 


Ai 




Bi 


Co 


MUL 




Ci 


Ao 


So 





Id 



"lo 



go ro — *■ o 

I I 



142 



Combinational circuits 



« 



3.15 Division 

The binary division requires to iterate the subtraction and the bit shifting, as the fol- 
lowing example shows: the divisor is compared with the dividend, starting from the 
most significant digits, subtracting the divisor from the dividend only if it is possible. 
That way, the integer division result (quotient) is made of Is digits when the subtrac- 
tion is possible and Os otherwise, whereas the remainder is what remains after all the 
subtractions. 

Figure 3.100. Unsigned integer division procedure. 

13-r5=2, remainder 3 1101^0101 = 0010 



can subtract? 



can subtract? 



can subtract? 



can subtract? 



0 0 0 110 1 

0 10 1 



0 0 0 1 1 

0 0 10 1 



0 1 



0 0 0 
0 0 0 



110 1 
10 1 



0 0 0 0 0 11 

0 0 0 0 10 1 




^remainder 



0 0 0 0 0 1 1 

To resolve the division problem with a combinational circuit the full-subtractor mod- 
ule can be used, including some more circuitry to check if the subtraction can be 
applied. As for the multiplication, a specific module can be designed. 



Combinational circuits 



143 



Figure 3.101. Conditional subtraction cell. 



Bo 



OKi > 




<Bi 



> OKo 



SF = full-subtractor 

M = minuend 

Si = input subrahend 

So = output subtrahend: copy for the next cell 
Bi = Borrow in 
Bo = borrow out 

OKi = OK in: the subtraction can be done, 
OKo - OK out: copy of OKi for the next cell 



v v 
D So 

With these cells, after every subtraction it is known if there is a borrow from the last 
Bo output {borrow out) on the left. If there is a borrow, then the subtraction can not 
be done, so the final borrow output is used inverted to select the subtracted value or 
the original one (the OKi input). 



144 



Combinational circuits 



Figure 3.102. Solution example for the unsigned integer division. 



dividend 



divisor 



Si 


M 


Bo 
OKi 


DIV Bl 

OKo 
D So 



3 


M 


Eo 


DIV a 


OKI 


OKo 
D So 




Si 


M 


Eo 


DIV a 


OKi 


OKo 
D So 



Si M 




Si M 




Si M 


■* 


Si M 


bo D | V a 




Bo D | V Bi 




Bo D(V B, 


*- 4- 


bo DiV a 


OKi OKo 
D So 




OKi 


QKb 

3 So 


-» -+ 


OKi 


OKo 
J So 


■+ -+ 


OKi OKo 
D So 



Si M 




Si M 




Si M 


Bo D | V Bi 




Bo D(V B, 




Bo D | V Bi 


OKi OKo 
D So 


-» -¥ 


OKi 


OKo 
3 So 




OKi OKo 
D So 




Si M 


-> 


Si M 




Si M 


Bo D | V B, 


*- *- 


bo D | V a 




Bo D | V B, 


OKi 


a a 

5 So 


-» -f 


OKi OKo 
D So 


-» 


OKi OKo 
D So 



When the division is signed, the following cases should be considered to decide the 
quotient and the remainder signs: 



Dividend 


Divisor 


Quotient 


Remainder 


+ 


+ 


+ 


+ 


+ 






+ 




+ 










+ 





To solve the signed division problem, a mechanism that changes the signs, before and 
after the division, might be the best way. 



Combinational circuits 



145 



Figure 3.104. Signed integer division: DIV4 can divide only unsigned numbers; 
minus4 changes the sign of a value if the input Signed is asserted. 



dividend 



A 

V 



b divisor 



Signed - 



[2] 



□ 



□ 



□ 



. [1] 



4- 


□ 


+ 


IN 


IN 


minus 


L 

-► 


minus 


minus4 




minus4 


OUT 




OUT 



DIV4 

Q R 
-*4 J£±_ 



[1] the more significant bit is used to know the sign of the value 

[2 ] dividend and divisor signs are different 

[3] the remainder sign depends only from the dividend 



minus 

minus4 



OUT 



quotient 



I* 



[3] 



4-4 



minus 

minus4 



OUT 



y remainder 



3.16 Magnitude comparator 

To do a magnitude comparator with two unsigned binary integers, it is necessary to 
compare the digits of both values, starting from the more significant ones. For every 
digit comparation it is necessary to establish which is the higher or if they are equal. 
The following figure shows the comparation between two simple logic values. 

Figure 3.105. 1 -digit magnitude comparator; the diagram on the right side is the 
same circuit with a more compact representation. 



« 



A>- 



B>- 



1 



> 



r 



> 



> AB A > B 

> EQ A = B 



-> BA B > A 



-o 



When more bits are compared, the match starts from the most significant bit, which 
prevails over the other. If the most significant bits are the same, the next digit should 



146 



Combinational circuits 



be checked to find which value is greater than the other; if all the digits of the two 
values are the same, the values are equal. 



Figure 3.106. 4-bit unsigned integer magnitude comparator. 



EQ A = B 



A >-7^- 



B >-r^- 



ABO 



EQO 



BAO 



0 s 



AB3 



EQ3 



> 



> 



-> ab A > B 



-3> BA B > A 



BA3 



Listing 3.107. 4-digit magnitude comparator, Verilog gate level implementation. 



module magnitude_ 


4 


(BA, EQ, AB, A, B); 


input [3:0] A, 


B; 




output 


BA, EQ, 


AB 


r 


wire [3 


:0] ab; 






wire [3 


: 0 ] eq; 






wire [3 


:0] ba; 






// 








assign 


#3 ab[0] 




A [0] &~B [0] ; 


assign 


#3 ab[l] 




A[l] &~B[1] ; 


assign 


#3 ab[2] 




A [2] &~B [2] ; 


assign 


#3 ab[3] 




A [3] &~B [3] ; 


// 








assign 


#3 ba[0] 




~A[0] &B [0] ; 


assign 


#3 ba[l] 




~A[1]&B[1]; 



Combinational circuits 



147 



ass ign 


#3 


ba [2 ] 


= ~A [2 ] &B [2 ] ; 


ass ign 


#3 


ba [3] 


= ~A[3] &B [3] ; 


// 








ass ign 


#3 


eq [01 


= ~ (ab [0] |ba [0] ) ; 


a q q i rrn 

OL k_J k_J _1_ \-4 J. 1 


#3 

IT 


en r 1 1 


= ~ (ab r 1 1 1 ba \ 1 1 ) ; 


ass ign 


#3 


eq [2 1 

^T. L ^ J 


= ~ (ab [2] |ba [2] ) ; 


ass icrn 


#3 


eq [31 


= ~ (ab r 3 1 Iba r 3 1 ) ; 


// 








assign 


#4 


EQ = 


eq [0] &eq [ 1 ] &eq [ 2 ] &eq[3] ; 


// 








assign 


#3 


AB = 


(ab[0] &eq[l] &eq[2] &eq[3] ) 
(ab r 1 1 &ecr T 2 1 &ea T 3 1 ) 
(ab r 2 1 &eq 1 3 1 ) 
ab [ 3 ] ; 


// 








assign 


#3 


BA = 

1 

1 


(ba[0] &eq[l] &eq[2] &eq[3] ) 
(ba r 1 1 &eq \2 1 &eq [31) 
(ba [2] &eq [3] ) 
ba [ 3 ] ; 


endmodule 







A common 4-bit magnitude comparator circuit is the 7485 (see il .4.2). 



Combinational circuits 



Chapter 



Arithmetic-logic unit 

4.1 Status flags 150 

4.2 Size truncation 152 

4.3 Sign inversion 154 

4.4 Addition and subtraction 156 

4.5 Shift and rotation 158 

4.6 Magnitude comparation 162 

4.7 Multiplication 165 

4.8 Division 171 

4.9 Logic unit 176 

4.10 Joining all the module together 177 

4.11 Bit sliced ALU 179 



addition 156 ALU 177 179 bit-size 152 bit slice 179 carry 150 comparation 162 
division 171 flag 150 multiplication 165 negative 150 overflow 150 156 158 rank 150 
152 rotation 158 shift 158 sign 150 154 size 152 status 150 subtraction 156 zero 150 

The arithmetic-logic unit (ALU) is a combinational circuit that contains the main 
calculation functions of a CPU. It is usually composed by some distinguished circuits, 
everyone of which does a single or a little group of calculations. These components 
are usually joined together through a multiplexer that selects the chosen result. 



150 



Arithmetic-logic unit 



« 



Figure 4.1. Simplified diagram of three components working together in a single 
ALU: everyone receives a couple of input values, but the output is selected by a 
multiplexer, through a control code that represents the function requested to the 
ALU. 



A 

v 



B 

v 



function 

> 



32 



32 



+ 



32 



X 



32 



32 



32 



00=addition (A plus B) 
01=multiplication (Ax B) 
10=division remainder (A% B) 
ll=division quotient (A/B) 



32 



32 



32 



32 



V 

result 



Where possible, the examples of the chapter are divided into 8-bit modules, which 
might be connected together to work with multiple bit sizes: 16, 32, 64. 

Common circuit components used to build an ALU are: 7483, 7485, 74181, 74182, 
74381 and 74382 (see u0.4). 

4. 1 Status flags 

For some kind of operation the ALU needs to remember a previous status; for exam- 
ple, an addition might be done in more than one step, taking into account the previous 
carry. Some flags are used to keep track of the status of previous operations; the most 
common ones are: carry, zero, sign and overflow. 



Name 


Common abbre- 
viation 


Description 


zero 


z 


Asserted when the last operation result was zero. 


negative sign 


N 


Asserted when the last operation result seems to 
be negative, because the most significant bit is 1. 



Arithmetic-logic unit 



151 



Name 


Common abbre- 
viation 


Description 


carry 


c 


Usually asserted when the last operation requires 
an additional digit to store the value and the ef- 
iective result is iruncaiea, dul usea aiso ior omer 
situations when a digit should be saved for iter- 
ated calculations. 


overflow 


0 
V 


The overflow is a condition that arise when the 
result of an operation is not valid because it is 
truncated at the most significant side or because 
li nas ine wrong sign, wnen aciciing iwo integer 
values there is an overflow if the last two carries 
are different. 



To verify a result equal to zero it is possible to check the output value with a NOR 
gate, which produces a 1 only if all the inputs are 0. It is also easy to find the sign of 
a value (assuming that the value is signed) checking the most significant bit. 

Figure 4.3. Module zn8: check for zero and for a possible sign. On the right side 
the same circuit appears with a compact diagram, where the eight input lines are 
grouped together in a single multiline port. 

D 

data 



D7 

v 



D6 

v 



D5 

v 



D4 D3 

v v 



D2 

v 



Dl 

v 



DO 

v 



V 



data 



/8 



NlOlO'-jniM-i-O 



V 



zero 



sign (negative) 



V 



V 



zero 



V 



sign (negative) N Z 

If it is required to operate with different bit-sized data, the above module can be used 
in paralel, adding a rank selection, like the following figure shows. 



152 



Arithmetic-logic unit 



Figure 4.4. Module zn32: zero and sign evaluation for integers from 8 to 32 
bits. The input port rk, which stands for 'rank', is a control function allowing to 
specify the desired bit-size: zero means 8 bits, up to 3 that means 32 bits. The 
module zn8 is described in figure 4.3. 



rk 

V 



D 

V 



data 



size ( rank): 

0 = 8 bits 

1 = 16 bits 

2 = 24 bits 

3 = 32 bits 



/ 32 



CO CM" 




Ah 



D 


D 


D 


D 


zn8 


zn8 


zn8 


zn8 


N Z 


N Z 


N Z 


N Z 



I — " 



sign (negative) v 
N 



Y zero 
Z 



4.2 Size truncation 



« 



The modules described in the following sections allow to operate on 32-bit values and 
on smaller sizes (multiples of 8). When the specified size is smaller than 32 bits, the 
results are valid only inside that particular rank and there might be also more contents 
that should be ignored on the more significant side, beyond the specified range. The 
following module allows to filter a value and even to extend the sign, based on a 
selected size. 



Arithmetic-logic unit 



153 



Figure 4.5. Module rk: filter and sign extension of a value, based on a requested 
size. 



m 

V 

/'s 



OfflfflN(Dlfltn«i-O0)fflN(DlfltnNT- 

P3(NC\ICJWIMOJOJCJOJIMT-T-T-T-T-T-T-T-T- 



sign: 

0 unsigned 

1 signed 

sg > 



0 



mnmnm uujuujuu ixjuumj yyyyyyyy 



rk> 

0 = 8 fcif 

1 = 16 bit 

2 = 24 bit 

3 = 32 bit 



0 

^1 





V 

out 



154 



Arithmetic-logic unit 



Figure 4.6. Module rk, identical to the previous picture, but designed in a more 
compact way. 



v in 



sign: 

0 unsigned 

1 signed 



sg > 




rk > 



size: 

0 = 8 bit 

1 = 16 bit 

2 = 24 bit 

3 = 32 bit 



out 



« 



4.3 Sign inversion 

To assist the multiplication and the division it is important a module that can invert 
the sign of a (signed) binary integer number. The module minus 8 works on 8 bits and 
it is used to build other inversion modules with a bigger bit-size. 



Arithmetic-logic unit 



155 



Figure 4.7. Module minus 8: 8-bit sign inversion. If the inputs M and Ci are 
asserted the sign is inverted, otherwise the value is not changed. The module ha 
is a common half adder. 



Co < 

carry out 



4- |4- 



b a 

ha 



i 

v 



I 1 



k w~ 




k k 




b a 






b a 






c ha 




<- 


c ha 






s 




s 





4- + 



b a 

ha 



ha 

s 



k k 




k k 




b a 






b a 






c ha 




<- 


c ha 




<- 


s 




s 





b a 

ha 



^ minus 



<Ci 

carry in 



N O! Ol A u ro 



156 



Arithmetic-logic unit 



« 



Figure 4.8. Module minus32: 32-bit sign inversion, made of four minus8 mod- 
ules, as described in figure 4.7. 



i 

v 



32 



M=0: 0 = +I 
M=l: 0 = -l 











M 




Co 


minus8 


Ci 






0 





I M 

co minus8 C i 

o 



i 

co minus8 

o 



Ci 



ft 



32 



M 

V 



I M 

co minus8 C \ 

o 



V 

o 

4.4 Addition and subtraction 

The following figure shows an 8-bit module that is able to add and subtract integer 
values, handling correctly either the carry or the borrow, signaling also the overflow 
(if the last two carries are different). 



Arithmetic-logic unit 



157 



Figure 4.9. Module as 8: addition and subtraction of 8-bit binary integers. The 
input / (function) selects the addition or the subtraction; the output O gives the 
overflow (if there is one). The module fa is a full-adder. 



A 

v 



Co^ o= 

carry out 
borrow out 



f=0: S = A+B+Ci, Co contains the final carry if there is one 
f=l: S = A-B-Ci, Co contains the final borrow, if there is one 



a b 






a b 




a b 




co fa ci 






co f a ci 




co fa ci 






r 


4- 4- 


4- 4- 


s 






s 




s 





a b 
co fa ci 



a b 
co fa ci 



B 

V 



NOOlJiUM-'O 



O 



overflow 



f Ci 

v v 





a b 




a b 




a b 




co fa ci 
s 




co fa ci 

s 




co fa CI 

s 




4- 4- 





carry in 
borrow in 



158 



Arithmetic-logic unit 



« 



Figure 4.10. Module as32: addition and subtraction with the possibility to con- 
trol the bit size. The module as 8 is described in figure 4.9. 



rk 

v 



size: 

0 = 8 bit 

1 = 16 bit 

2 = 24 bit 

3 = 32 bit 




4.5 Shift and rotation 

The following figure shows a module that is able to do a logical an arithmetical shift 
on 8 bits. The ports lin, lout, rin and rout (left/right in/out) are there to allow a 
shift and rotation on multiples of 8 bits. The output ports CI and Cr (carry left/right) 
contain always the bit value that is shifted outside (on the left or on the right side), 
whereas the output port O (overflow) is asserted only when an overflow is produced, 
due to an arithmetic left shift that changes the sign. 



Arithmetic-logic unit 



159 



Figure 4.11. Module sh8: 8-bit logic and arithmetic shift. 



0=left 
1 =right 



lin > 



lout 




> rout 

right out 



< rin 

right in 



left 
side 
carry 



[1] Arithmetic shift: 

- the shift should be arithmetic; 

- it should be a right shift; 

- the most significant bit should be 1. 
[2] Overflow: 

- the shift should be arithmetic; 

- the most significant bit should not have changed. 
[3] Connection to the most significant digit or to the sign. 
[4] Connection to the least significant digit. 
[CI] Left carry: 

- it should be a left shift; 

- the original most significant digit is 1. 
[Cr] Right carry: 

- it should be a right shift; 

- the original least significant digit is 1. 



right 
side 
carry 



160 



Arithmetic-logic unit 



Figure 4.12. Module sh32: from 8 to 32-bit logic and arithmetic shift. The C 
output (carry) returns the bit value that is shifted outside either on the left or the 
right side. The module sh8 is described inside the figure 4.11. 



0=logic shift la 
l=arithmetic shift 



rk 
v 



carry 



V 



size: 

0 = 8 bit 

1 = 16 bit 

2 = 24 bit 

3 = 32 bit 

-V, 



lr 

V 0=left 
l=right 



dd 



2 



0± 



2n 



A 

V 

K 



32 



5? 



la 

lout 
lin 

CI O 



Sh8 



Cr 



la 


lr 


A 




la 


lr A 




la 


lr A 


lout 


sh8 


rin 


«- 


lout 


rin 

sh8 


«- 


lout 


rin 

sh8 


lin 




rout 


-*> 


lin 


rout 




lin 


rout 


CI 


0 S 


Cr 




CI 


0 S Cr 




CI 


0 S Cr 



"10 



Y overflow 

o 



/ 32 



Arithmetic-logic unit 



161 



Figure 4.13. Module ro32: from 8 to 32-bit rotation. As there is no 'arithmetic' 
rotation, there is no overflow either. The module sh8 is described in figure 4.1 1. 



rk 



size: 

0 = 8 bit 

1 = 16 bit 

2 = 24 bit 

3 = 32 bit 



carry 



lr 

v 0=left 
1=right 



A 

V 

/as 



lout 



nn 



sh8 



lin rout 
CI 0 S Cr 



0 

Hi 



sh8 



CI O S Cr 



no 
1 



lout 



nn 



sh8 



lin rout 
CI O S Cr 



/E 



lout 



nn 



sh8 



lin rout 
CI O S Cr 



+ l+ 



/; 



/* 



•/ 

CO 
3 — 

V 

s 



162 



Arithmetic-logic unit 



« 



Figure 4.14. Module rc32: rotation with carry (the input carry is inserted from 
one side and the output carry, at the opposite side, is saved for the next rotation). 
The module sh8 is described in figure 4.1 1. 



rk . 

v size: 

0 = 8 bit 

1 = 16 bit 

2 = 24 bit 

3 = 32 bit 



0 



Co 



lr 

v 0=left 
1=right 



A 



V 

✓ '32 



Ci 

v carry in 



Sh8 



Gl O S Cr 



I 



Sh8 



CI O S Cr 



nr 



Sh8 



CI O S Cr 



la 


lr 


A 


lout 


Sh8 


rin 


lin 




roul 


CI 


0 s 


Cr 



carry out 



s 



4.6 Magnitude comparation 

The module cmp8 compares the magnitude of two unsigned values, asserting a differ- 
ent output port depending on the three possible conditions: A>B, A<B, A=B. 



Arithmetic-logic unit 



163 



Figure 4.15. Module cmp8: 8-bit integer unsigned magnitude comparation. 



A 

v 

/'b 



B 

v 



r^tOLO^otM-'-o 



IT' '^JT 1 "i 



9 



9 



□ □UUtJ 



9 



U~~U 



"IT 



u 



■n r 



eq 



A=B 



V 



V 



A>B 



B>A 



ab ba 
The module cmp8 can be used to compare two values with a multiple bit size; in 
that case it is possible to introduce extra logic to consider even the sign: if the input 
values to be compared are signed and if the signs are different, the result should be 
reversed. The module cmp32 compares two 32-bit values, returning a 32-bit value: 0 
if the values are equal, +1 if A>B; -1 if A<B. 



164 



Arithmetic-logic unit 



Figure 4.16. Module cmp32: signed or unsigned 32-bit magnitude compare. The 
module cmp8 is described in figure 4.15. 



v 



0 = unsigned 

1 = signed 




A andB 
signs are 
different 



A 

V 



/ / 32 



B 

V 



/ / 32 



/ 




A B 


A B 


A B 


A B 


cmp8 


cmp8 


cmp8 


cmp8 


ab eq ba 


ab eq ba 


ab eq ba 


ab eq ba 



□ 0 U U" "0 



if A and B signs are 
different, the result 
is reversed 



ry 



eq 




the 'eq' output 
is not used 



V +1 ifA>B 
Z 32 -lifA<B 
▼ 0 ifA=B 

M 



Arithmetic-logic unit 



165 



The module cmp32 does not allow to reduce the bit range to be compared; therefore, 
if there is the need to control the input bit size, it is necessary to add the module rk 
as a filter (figure 4.5). 

Figure 4.17. Input filter with the module rk (figure 4.5). 



sg > 

0 = unsigned 

1 - signed 




rk 

V 



size: 

0 = 8 bit 

1 = 16 bit 

2 = 24 bit 

3 = 32 bit 



4.7 Multiplication 

As already described in a previous chapter, the multiplication requires a special mod- 
ule that adds the result of the AND operation between the two input values. This 
module is recalled inside the following figure. 



« 



166 



Arithmetic-logic unit 



Figure 4.18. Module mul: 1-bit multiplication. This module is used inside the 
one that multiplies 8-bit values. 



bo < 



co < 



ao < 




si = sum input 
ai = a input = moltiplicand 
bi = b input = moltiplicator 
ci = carry in 

so - sum output - ((aiAND bi) + si + ci) 

ao - ai 

co = carry out 

bo = bi 



The following figure shows the module mul 8, which is a 8-bit multiplier with all the 
required ports to connect with other similar modules. 



Arithmetic-logic unit 



167 



Figure 4.19. Module mul8: 8-bit multiplication. 



C/3 ' 



11 



•I-H : 

C/5 



00 

•I— I 



a 8 ak | £ 8 ak | s s ak 



S E8 J 



L3 



1 8 

s s a 



1 B 

ass 



I B e 



, 1 8 
2 8 8 



1 8 



» J 8 



1 8"* 
S 8 § - 



s 8 a 



R 



ssa^-| ssa^-n ssa^i s 88^ s s a ^ s s a ^ s 8 a ±i 



8 £ 8 8 S 88^ S88^-n S 88^ £ S 8 ±n £88^ S S $ 



1 8 



2 



CZ3 



o 



00 

-* O 

C/2 



O 
c3 



168 



Arithmetic-logic unit 



As the module mul8 is complex even if used alone, the following figure shows how 
to use it to multiply 8 -bit values. 

Figure 4.20. How to use the mul8 alone. 



10 



ON 
OFF 



r 



8 

7 


Si7 
bo 


siO 


ai 
bi 




/ 4- 


coO 


mul8 


ciO 




4r 


C07 




ci7 




-► 


si8 




soO 






so8 


ao 


so7 



/8 



10 



ON 
OFF 



o 



10 



16 



To proceed gradually, the following figure shows a module that multiply 16-bit values, 
using fourmul8 modules. 



Arithmetic-logic unit 



Figure 4.21. Module mull6: 16-bit modules. The module mul8 is described in 
figure 4.19. 



A 

V 



16 



Si7 


SiO 


ai 


bo 






bi 


coO 


mul8 


ciU 


co7 




ci7 


si8 




soO 


so8 


ao 


so7 



A 



- a>7 
o 

I 



8 
4^ 

7 



4-4- 

7 



Si7 


SiO 


ai 


bo 






bi 


coO 




ciO 


co7 


mul8 








ci7 


si8 




soO 


so8 


ao 


so7 



si7 


SiO 


ai 


bo 






bi 


coO 


mul8 


ClO 


co7 




ci7 


si8 




soO 


so8 


ao 


so7 



8 
4^ 

7 



4-4- 

7 



cn 
o 



"^7 



Si7 


SiO 


ai 


bo 






bi 


coO 




CiO 


co7 


mul8 








ci7 


si8 




soO 


so8 


ao 


so7 



^7 



05 
O 



4m 



' SI 

CO o 



B 

V 



7:0 



15:8 



16 



32 



V 



Q 



170 



Arithmetic-logic unit 



Figure 4.22. Module mul32: 32-bit signed and unsigned multiplication. The 
module mul8 is described in figure 4.19, whereas the modules minus - are de- 
scribed starting from the figure 4.7. 



A 

V 







M 


minus32 






3 





8 



^1 



si7 


siO 


ai 


bo 




bi 


coO 




ciO 




mul8 




C07 




Ci7 


Si8 




SO0 


so8 


ao 


so7 



si7 


siO 


ai 


bo 




bi 


coO 




ciO 




mul8 




C07 




Ci7 


si8 




SOO 


so8 


ao 


so7 



J2S 



si7 
bo 
coO 
co7 



ci7 
soO 
so7 



/l 



si7 


siO 


ai 


bo 




bi 


coO 


mul8 


ciO 


co7 




ci7 


si8 
so8 


ao 


soO 
so7 



n 



si7 


SiO 


ai 


bo 




bi 


coO 




ciO 




mul8 




co7 




ci7 


si8 




soO 


so8 


ao 


so7 



/'8 



si7 


siO 


ai 


bo 




bi 


coO 




CiO 




mul8 




C07 




Ci7 


siS 




soO 


so8 


ao 


so7 



si7 


siO 


ai 


bo 




bi 


coO 




CiO 




mul8 




co7 




ci7 


SiS 




soO 


S08 


ao 


S07 



Si 



si7 


siO 


ai 


bo 




bi 


coO 




ciO 




mil 18 




co7 




ci7 


SiS 




soO 


S08 


ao 


S07 



soO 
so7 



Si7 


SiO 


ai 


bo 




bi 


coO 




ciO 




mul8 




C07 




Ci7 


siS 




soO 


so8 


ao 


so7 



li 7 



^8 f 



si7 


siO 


ai 


bo 






bi 


coO 




ciO 




mul8 






co7 




ci7 


siS 




soO 


so8 


ao 


so7 



si7 


SiO 


ai 


bo 




bi 


coO 




ciO 




mul8 




C07 




ci7 


siS 




soO 


so8 


ao 


so7 



Si 



Si h t X h K Si X t >7 >8 S 

♦ I* I* k k k k k k k k k l_L 



/7 



si7 


siO 


ai 


bo 




bi 


coO 




CiO 




mul8 




co7 




ci7 


SiS 




soO 


S08 


ao 


S07 



si7 


siO 


ai 


bo 




bi 


coO 


mul8 


ciO 


co7 




ci7 


siS 




soO 


so8 


ao 


so7 



/'8 



Si7 


SiO 


ai 


bo 




bi 


coO 




ciO 




mulS 




C07 




ci7 


siS 




soO 


so8 


ao 


so7 




Mb 





Si s 



Si7 


SiO 


ai 


bo 




bi 


coO 




ciO 




mul8 




C07 




ci7 


siS 




soO 


so8 


ao 


so7 









/l 



/S4 





M 


minus64 


0 






/ 


^64 



Q 



B 



sg 

v 







M 


minus32 




( 


3 





Arithmetic-logic unit 



171 



4.8 Division 



« 



As already described in a previous chapter, the division requires a special module to 
subtracts the divisor from the dividend. This module is recalled inside the following 
figure. 

Figure 4.23. Module div: 1-bit division. This module uses an f s module, which 
is a full- subtracter (see section 3.10). 



m 

v 



SI 

V 



> 



bo < 




bo fS 



m 



bi 



<bi 



fs = full subtractor 

m = minuend 

si = input subtrahend 

so = output subtrahend 

bi = input borrow 

bo = output borrow 

oki = input ok: the subtraction is valid 

oko = output ok: the subtraction is valid 



oki > 



> oko 



V 
d 



V 
so 



172 



Arithmetic-logic unit 



Figure 4.24. Module div8: 8-bit integer unsigned division. There are 64 div 
modules, used to subtract the divisor from the dividend, until the quotient and the 
remainder are found. The module div is described in figure 4.23. 



O 

03 



: E % ^ — — £ % - e £ - 

a S g g__gg -m fi g 



S g | |_g__g_J 



■a S j g__gg 



o 

T3 



a j 



■- E J . J-J E j , 



! E « * 

.as 



1- 
B 



■■it" 



■ E i * 

■» a j 



■s a j a a g 



■a S j ajj 



■ E t x 

a 8 



r-- 

T3 



Itr rjir 



00 
•T3 



g 8 g | la £ g 



1 ~ * E « 

■.Si 



■ E « . 

■• a s 



. E « .3- 

. a s 



■n 8 j -m 8 | 



TJT 



Mi 



Arithmetic-logic unit 



Figure 4.25. Usage example for the module div8 alone. The module div8 
described in figure 4.24. 

divisor 



dividend 



ON f 
OFF t 



ON t 
OFF E 



10 





m8 


si m7 


mO 


7 










d8 










div8 




4- 


bo 


bi 




oki 




oko 




d7 


d0 


so 



□□□□□□□□ 



n 



quotient 



I II II" 



reminder 



10 



DDDDDDDD 



/8 



174 



Arithmetic-logic unit 



Figure 4.26. Module divl6: 16-bit integer unsigned division. Four modules 
div8 are used. The module div8 is described inside the figure 4.24. 



o 



B 

V 



16 

divisor 



/ 7 



m8 


si m7 


mO 




7 


d8 


div8 






8 




bo 


bi 


*■ 


8 




oki 




oko 


■* 






d7 


dO 


so 









O) 



A 

V 



dividend 



16 



I I 
r- o 



m8 


si m7 


mO 


d8 






bo 


div8 




bi 


oki 




oko 


d7 


dO 


so 



m8 


si m7 


mO 




7 


d8 


div8 






8 


bo 


bi 


•«- 


8 


oki 




oko 


-► 




d7 


dO 


so 







m8 

d8 
bo 

oki 

d7 



m7 mO 



div8 



dO 



' O) 
~g o 



bi 

oko 
so 



15:8 



7:0 



quotient 

16 



> Q 



reminder 

Y 
R 



Arithmetic-logic unit 



175 



Figure 4.27. Module div32: 32-bit signed integer division. There are sixteen 
div8 modules and four minus32 modules to control the sign if the input data 
is meant to be signed. The module div8 is described in figure 4.24, whereas the 
module minus32 can be found in figure 4.8. 



B divisor 

/ '32 



S v ^ signed values 



A dividend 

V 



signed inputs, 



mS si m7 mO 



n in. 



d7 do 



* \± 



m8 
d5 


div8 


mO 


bo 


bi 


cki 
07 


dO 





rn8 si m7 mO 



d7 dO 



m8 si m7 mO 
d8 

bo div8 bi 

oki oko 

d7 dO so 



d7 dO 



si m7 mO 



d7 do 



8 



mS si m7 mO 



d7 do 



m8 
dS 


div8 


7 mO 


bo 


bi 


oki 

d7 


dO 





,'7 



/'7 



si m7 mO 



d7 dO 



/l 



si m7 mO 



d7 dO 



rn8 si m7 mO 



d7 dO 



8 

*- / *- bo 



si m7 mO 



d7 do 



d7 dO 



3 



d7 do 



m8 si m7 mO 



d7 dO 



^1 



d7 dO 



,'32 



minus32 



reminder 



R 



s 

3- 

to 

05' 



R 

5! 
a. 

SI 



'5:8 X < 



quoziente 

32 



« 



176 

4.9 Logic unit 



Arithmetic-logic unit 



A logic unit is a module that calculates bitwise boolean operations. The common 
operations available are usually NOT, AND, OR and XOR, but the example in the 
following figure shows all the cases of the table 3.4, even if many of them are unnec- 
essary. 

Figure 4.28. Module logic32: all the sixteen logic operations that can be denned 
in a combinational circuit with two input ports ad a single output. In this case, 
every logic gate is multiplied 32 times in paralel. 



f: 
00 

1NOR 

2A-B 

3 A 

4A-B 

5B 

6 XOR 

7NAND 

8 AND 

9NXOR 

10 B 

11A+B 

12 A 

13A+B 

14 OR 

151 

f> 



A 

V 



B 

V 



32" 



32 
^32 



/ 



32 



32 



32 



32 



32' 



X 32 



32 



32' 



/ 



32- 



32 



32 



/ 



o<T 



32 



32 



o 



^3Z 



32 
/ 



33- 



32 



o„ 



32 



32/ 32 



32 



32 



32 



/ 32 



32 



32 



32 



\0 



15, 



V, 



dd 



v 

L 



Arithmetic-logic unit 



177 



4.10 Joining all the module together 

« 

In the following figure there is an ALU with all the modules described in the previous 
sections. Please notice that the proposed solution is not optimal and it has only a 
demonstration purpose. 



178 



Arithmetic-logic unit 



Figure 4.29. Module alu32: 32-bit ALU. The input F represent the requested 
function that the ALU should execute. 




Jt-Ot-Ot-Ot-Ot-Ot-0->-0->- 
>Ot-t-00->-->-00->-t-OOt-t- 
>OOOt-->-->-->-OOOOt-t-t-t- 
JOOOOOOO->-->-->-t-t-t-t-t- 
JOOOOOOOOOOOOOOO 
JOOOOOOOOOOOOOOO 
JOOOOOOOOOOOOOOO 
JOOOOOOOOOOOOOOO 



< < 

O T- 

o o 
o o 
o o 

noo 
woo 
ffl o o 



< m < m < co • 

Ot-Ot-Ot-Ot- 
OOt-t-OOt-t- 
OOOOt-t- t- t- 

00000000 

OJOOOOOOOO 



O T- O T- 

O O T- T- 

o o o o 

o o o o 

i £ £ £ £ Bl 



■ O i- 

3 T- T- 

5 O O 



o o o o 



o o 
o o 

(MOO 

^oo 



CD 

< < 

o o 

o o 

o o 

, o o 



Arithmetic-logic unit 



179 



4.11 Bit sliced ALU 

If the requested functions are limited and the addition can be obtained with the simple 
ripple-carry method, it is possible do design a bit-sliced ALU that is a single bit ALU, 
which can be expanded to any bit- size. 

Figure 4.30. Module as: f=0 requires the addition with carry; f=l requires the 
subtraction with borrow; if the output carry is different from the input one, there 
is an overflow. 



« 



Co 



carry out 
borrow out 




f=0: SUM=A+B+Ci 
f=l: SUM=A-B-Ci 



— <Ci 

carry in 
borrow in 



overflow 



180 



Arithmetic-logic unit 



Figure 4.31. Module logic: 1-bit logic unit. The value received by the input / 
selects the logic operation. 



f 

v 



f: 
00 

1 NOR 

2A-B 

3 A 

4A-B 

5B 

6XOR 

7NAND 

8 AND 

9NXOR 

10B 

11A+B 

12 A 

13A+B 

14 OR 

151 



A 

V 



B 

V 



0 



V, 



dd 



15 



Y 

LOGIC 



Arithmetic-logic unit 



181 



Figure 4.32. Module ltgt: magnitude comparation. The comparation is made 
at the bit level, using the input carry if the values are the same. The result is 
transferred to the next module through the output carry. The module is made of 
two parts: It (A<B) and gt (A>B). The overall module does the first and the 
second comparation, based on the function /. The equality match is not done, 
because it can be obtained with the NXOR operator. 




Co < 




<Ci 



Figure 4.33. Modules shl and shr: left and right shift. The shift is done using the 
carry: the left shift uses the 'normal' carry, whereas the right shift uses a reversed 
carry line where the names Di and Do are used. The shift does not consider the 
sign; the input / is used to select the operand to shift: either A or B. 
f A B f A B 



v 



V V 



V 



V V 



0 1 



,0 1 



Co 



v 
o 



<Ci 



V 

V 

SHL 



Di> 



V 
SHR 



"> > Do 



182 



Arithmetic-logic unit 



Figure 4.34. Module z: zero. It verifies if the value is zero and if all the previous 
ones are reporting the same (through the carry line). The input / allows to select 
which operand to check. 



f 

V 



A B 

V V 



0 1 



zero 



Co <r 



o- 



<Ci 



Figure 4.35. Module alu: 1-bit ALU, made of the previous modules. 



r > 



Co- 



logic 

LCCIC 



t A B 

Co Itgt o 



omfilll? 



Di 



shr 

SI IK 




Do 



Co as 

o SUM 



-< Ci 



V 



j m 1 




Arithmetic-logic unit 

Figure 4.36. 4-bit ALU using four alu modules. 



183 



101 



ON c 

offE 





on 




off 



[1001 



ON c 
OFFE 



/ 4 



U L_l 
I I I I 



[HI 



ON c 

offE 



/ 4 



u u 
I 1 1 I 



10 



r 


f 


A 


B 




f 


A 


B 




t 


A 


B 




f 


A 


B 




Co 


alu 


Ci 


M- 


Co 


alu 


Ci 




Co 


alu 


Ci 


«- 


Co 


alu 


Ci 




Di 

0 


Y 


Do 


-** 


Di 

0 


Y 


Do 




Di 

0 


Y 


Do 




Di 

0 


Y 


Do 





ft 


on 


<- 




off 



co ro — 1 o 



lOOODl 


/ 


u 

4 

I 7^ 


MM 
Ml Ml 






no 



Arithmetic-logic unit 



Chapter 



Latch and flip-flop 

5.1 Propagation delay 185 

5.2 Truth tables 187 

5.3 SR latch 188 

5.4 Bounce-free switch 193 

5.5 Gated SR latches 193 

5.6 SR flip-flop 195 

5.7 Time: setup/hold and recovery/removal 198 

5.8 D latch and D flip-flop 199 

5.9 T flip-flop 203 

5.10 JK flip-flop 204 

5.11 Troublesome JK flip-flops 207 



bounce free 193 delay 185 D flip-flop 199 Earle latch 199 edge-triggered 195 
flip-flop 185 195 gated D latch 199 hold time 198 JK flip-flop 204 207 latch 185 
master-slave 199 memory 185 propagation delay 185 recovery time 198 removal 
time 198 sequential circuit 185 setup time 198 SR flip-flop 195 SR latch 188 switch 
193 transparent latch 199 T flip-flop 203 



The combinational circuits transform the input data into the output data, according to 
a certain function, without taking into account any previous status: the data is trans- 
lated always in the same way, after a little amount of time. Because of this charac- 
teristic, the combinational circuits are said to be memoryless. Instead, a sequential 
circuit takes into account the dynamic on which the input data is received, keeping a 
status, which is updated by the circuit itself and which is in fact an additional source 
of input data that influences the output result. 

The sequential circuits are based on components known as memories, which are made 
of latches or flip-flops. A latch is a circuit whith some kind of feedback, by which one 
or more output lines becomes input again; a flip-flop is a sophisticated latch which is 
responsive to the variation of a data. 



186 



Latch and flip-flop 



5.1 Propagation delay 

Every combinational circuit reacts to the input data change updating the output with 
a little time delay, known as the propagation delay. The amount of the delay time 
depends on the physical and mechanical characteristics of the real circuit. 

Figure 5.1. An impulse signal traversing a buffer shows on the output a little 
delay. 





a 


oscillator 


-► 



q 























propagation delay 



The propagation delay might be used to produce a short impulse, as it shows the 
following figure. 



Latch and flip-flop 



187 



Figure 5.2. A short impulse produced by the delay propagation. 

b 



oscillator 



delay introduced by the inverter 

i 



b 

q 



n 



n 



J~L 



delay introduced by the AND gate 

5.2 Truth tables 

The truth table is a way to explain the combinational circuit behaviour, whereby the 
output values are shown as functions of the input ones, without considering either 
the propagation delay or the dynamic that the input data might have. To explain a 
sequential circuit behaviour a kind of truth table might be used, but if they are used, 
the notations should be understood depending on the particular context. The following 
sections introduce latches and flip-flops, which might be influenced by the input data 
signal variations, therefore the following notation is used: 



« 



0 stable 0 

_/" variation from 0 to 1 , or positive edge 

1 stable 1 

"\_ variation from 1 to zero, or negative edge 



o j 



\_ o J 



\ o 



188 



Latch and flip-flop 



5.3 SR latch 



« 



The simplest sequential circuit that keeps its status memory is the one shown on the 
following two figures, made either with NOR or NAND gates. With the NOR gates 
example, the Q output is initially unknown and might be either 0 or 1 ; then, asserting 
the S input (set) even with a short positive impulse, the Q output is asserted (activated) 
and it remains active until the R input (reset) remains negated. That is: a short positive 
impulse to the S input sets the output, whereas the same impulse to the R input resets 
the output. With the example with NAND gates, the inputs S and R are negated, so 
that the set and reset impulse should be negative. 

Figure 5.5. Simple set-reset latch with NOR gates. 



s 



R 



Q 



0 
0 
0 
0 

J 
J 
J 
J 



0 

_/■ 

1 

-\ 

0 

_/ 
1 

-\ 

0 

_/■ 

1 

-\ 

0 

_/ 
1 

-\ 



unchanged 



s> 



R> 



set 



reset 



Or 



^> Q 



1 
1 
1 
1 

-\ 
-\ 
-\ 
-\ 



0 
0 

o 
i 
o 
o 
i 
i 

0 
0 

1 
1 
o 
o 



not allowed! 



Latch and flip-flop 



189 



Figure 5.6. Simple set-reset circuit with NAND gates. 



S >- 
R > 



)o 



Q 



s 


R 


Q 


0 


0 


l 


0 


J~ 


l 


0 


1 


l 


0 


"\_ 


l 


_/" 


0 


0 


_/" 


_/" 


non allowed! 


J- 


1 


1 


_/■ 


-\_ 


0 


1 


0 


0 


1 


J- 


0 


1 


1 


wnchanged 


1 


-\_ 


0 


"\_ 


0 


1 


"\ 


J- 


1 


"\_ 


1 


1 


"\_ 


-\ 


1 









The two figures above show a circuit and the corresponding truth table, which high- 
lights a condition that is not allowed: the NOR circuit should not let both inputs 
change from 0 to 1 simultaneously, whereas the NAND one should not let both in- 
put change from 0 to 1 simultaneously. The reason for the not allowed condition is 
explained later. 

The above figures represent a simplified version of kind of circuit known as SR latch, 
which usually has another negated output, Q, which gets the opposite value of Q. 

Figure 5.7. SR latch with NOR gates. 



R> 



S> 



Q 



Q 





S Q 
R Q 













S 


R 


Q 


Q 


0 


0 


unchanged 


0 


J- 


0 


l 


0 


1 


0 


l 


0 


-\_ 


0 


l 


J- 


0 


1 


0 


J- 


J- 


0 


i 


_/■ 


1 


0 


l 


_/" 


-\_ 


1 


0 


1 


0 


1 


0 


1 


J- 


0 


1 


1 


1 


0 


0 


1 


-\_ 


1 


0 


-\_ 


0 


1 


0 


-\_ 


J- 


0 


1 


-\_ 


1 


0 


1 


-\_ 


-\_ 


not allowed! 



190 



Latch and flip-flop 



Figure 5.8. SR latch made with NAND gates. 



o- 



R > 



o- 



Q 



Q 



R 



S> 



°— ? > Q 



o— * > Q 



o 
O 


K 


Q 


Q 


O 


o 


l 


l 


o 


_/ 


l 


0 


o 


1 


l 


0 


o 


\_ 


l 


0 


_/ 


g\ 

O 


0 


l 


_/ 


_/ 


not allowed! 


_/ 


1 


1 


0 


_/ 


\_ 


0 


l 


1 


o 


0 


l 


1 


_/ 


0 


l 


1 


1 


unchanged 


1 


~\_ 


0 


l 


-\_ 


0 


1 


0 


-\_ 


_/" 


1 


0 


-\_ 


1 


1 


0 


-\_ 


-\_ 


1 


0 


ging the meaning of the input lines. 


S 


R 


Q 


Q 


0 


0 


l 


l 


0 




0 


l 


0 


1 


0 


l 


0 


"\_ 


0 


l 


J- 


0 


1 


0 


J- 


_/" 


not allowed! 


J- 


1 


0 


l 


J- 


-\_ 


1 


0 


1 


0 


1 


0 


1 


_/" 


1 


0 


1 


1 


unchanged 


1 


-\_ 


1 


0 


-\_ 


0 


1 


0 


-\_ 


J- 


0 


1 


-\_ 


1 


0 


1 


-\_ 


-\_ 


1 


0 



The SR latch made with NAND gates is equivalent to the NOR one with the input 
ports negated; however, the SR latch with NAND gates is also used changing the 
input port names as it is shown in the last figure above, but this way the behaviour 
is no more equal to the NOR gate version, although it is nearly the same. For that 
reason, when an SR latch is drawn as a box, it is necessary to specify which truth 
table is used; anyway, the SR latch alone is used very seldom and it is advisable to 



Latch and flip-flop 191 
depict it with logic gates and not only as a box. 

Figure 5.10. NOR SR latch traces showing two critical situations: the first time 
both the input ports are asserted and becomes negated simultaneously; the second 
time the inputs impulse is too short. 




r_t 



Q 




Q—T^. 



1 



I 



_r~L 



i 



reset set 

Y 

set and reset to zero at the same time 



nrwnnn 

JLMJLUULR 



LLrrnmnnnnTL 



J111111111JLJLFL 
resonance 



J L 



anjuu ruinjiL 

resonance 



n 



too short pulses 



The figure above shows a NOR SR latch timing diagram, where the propagation delay 
is evidenced, but especially is visible what happens when the input ports drop to zero 
simultaneously: because of the propagation delay, the two outputs remains for a while 
to zero, but then, as the inputs are now zero, the outputs are activated and that start 
a loop of deactivation and activation. This is the problem that imposes to avoid to 
drop to zero the input ports simultaneously. But even a too short pulse might create 
troubles: the input impulse should be long enough to allow the latch to change its 
state (if that impulse should change it). 

The SR latch is the basis for all other latches and flip-flops; that is why it is important 
to know in how many ways it can be implemented, as the following figure shows. 



192 



Latch and flip-flop 



Figure 5.11. SR latch in many equivalent implementations, where care should 
be given to the input ports order. On the left side there are the active-high input 
versions, whereas on the right side appear the ones with active-low inputs. The 
most common SR latches are highlighted: NOR and NAND. 



R 


\ 




— Q 


S 








1 


>- 


^— Q 



R 



O 



Q 



Q 



R 



R 

S 



R 



— O 



S— 

s— ^ 



-o 



-o 



o 



-o 



Q 



Q 



Q 



Q 



Q 



Q 



R- 



S 
S 



R 



R 



rO 



-O 



— o 

r-O 



Q 



Q 



Q 



Q 



o 



Q 



o — • 



Q 



Latch and flip-flop 



193 



5.4 Bounce-free switch 

When building real electronic logic circuits, switches are often used, but in the real 
world, these components have the 'bounce' problem, which means that opening or 
closing the switch some unwanted impulses are generated. To avoid these impulses 
the SR latches are used, for example in the way shown by that the figure below. 

Figure 5.12. SR latch used to filter the bounces produced by a switch. 



vcc 




vcc 



Q 



Q 



5.5 Gated SR latches 

The SR latch can be extended including two control gates to enable the set-reset input 
lines. In practice the new SR latch has an additional input port used to enable the other 
two inputs: when the enable input is asserted, the SR latch work as usual, but when it 
is negated, the other input lines are just ignored. 



194 



Latch and flip-flop 



Figure 5.13. Gated SR latch: when the E input (enable) is asserted, it works as 
the usual SR latch; when the E input is negated, the other inputs are ignored. The 
circuit appears in the two common versions, together with the usual symbology. 



R 



TO 



Q 




> 



> 



Q 



R 



> 



Q 




The two diagrams in the above figure are equivalent and it can be demonstrated with 
the De Morgan's laws. 

Figure 5.14. Gated SR latches equivalences. 



(a + b)= a • b 





o 





o^e> 



a + b =(a • b) 



1 



The gated SR latch does not resolve the resonance triggering problem already de- 
scribed: the enable input should be asserted only when the other inputs are in a valid 
condition, avoiding the case when both S and R are asserted at the same time, because 
when the enable input becomes negated, it would trigger the resonance. 



Latch and flip-flop 



195 



Figure 5.15. Truth table for a gated SR latch, limited to the most significant cases. 



R 

E 

S- 

s- 

E- 
R 



□ 



o- 



o- 



o- 



iO 



Q 

- Q 

-Q 

- Q 



E 


s 


R 


0 0 


0 


X 


X 


unchanged 


_/"\_ 


0 


0 


unchanged 


/— \ 


o 


1 


0 1 


_/"V 


1 


0 


1 0 


_/"\_ 


1 


1 


not allowed! 


1 


-\_ 


-\_ 


not allowed! 


"\_ 


1 


1 


not allowed! 



When a gated SR latch is turned on, the initial output status is undetermined. To be 
able to initialize the circuit it is necessary to extend the input ports of the internal 
SR latch, as the following figure shows. It should be noticed that, depending on the 
internal SR latch implementation, the initialization signal might be asserted high or 
low. 

Figure 5.16. Gated SR latch with initialization inputs: when the input P (P) input 
is asserted (preset), the Q output activation is forced; when the C (P) input is 
asserted (clear), the Q output activation is forced (clearing the other output port). 



C 
R 

E 



clear 



Q 




S Q 



E 
R 



C 



P 

S 



preset 



preset 



R- 
C 



Q 



Q 



S P Q 
E 

R c Q 



clear 



5.6 SR flip-flop 

The gated SR latch has an enable input that, when asserted, allows to receive set and 
reset assertion from the other inputs, but if the enable input is to be used as a way 
to update the latch in a precise moment, the enable signal must be short enough to 
avoid that any change can happen in the meantime. To resolve properly the problem, 
two gated SR latches can be connected, one after the other as 'master' and 'slave', 
inverting the enable input to the second one: this way the output of the whole circuit 



« 



196 



Latch and flip-flop 



is updated when the enable signal passes from high to low, that is the negative edge: 
this kind of latch is a flip-flop and it might be triggered with a negative or a positive 
edge, depending on the implementation. 



Figure 5.17. Positive and negative edges of a signal, 
positive edge 



negative edge 



Figure 5.18. Negative edge triggered SR flip-flop: when the enable signal goes 
from 1 to 0, the flip-flop is updated. The circuit is shown starting from the block 
diagram and then with the common gate implementations. It should be noticed 
that the enable input is now called 'clock' and it is usually shown as a triangle. 





Q 






Q 




s 


-► 


-► 


S 




E 
R 






-► 


E 








Q 


-► 


■> 


R 


Q 


-► 



l> 



s 

> 


Q 


R 


Q 



negative edge triggered 
SR flip-flop 



Ft 



Clk 



> 



> 



Q 



Latch and flip-flop 

s — 

Clk 



197 



R 



> 



> 



> 




> 



> 



I 


= >r 




1 




-• — 



Q 



Q 



s 

R 

Clk 

Q 

Q 



Figure 5.19. Negative edge triggered SR flip-flop, with initialization inputs. 

C 



S P Q 
E 



S P Q 



Clk — 

s— 



O^L> 



F=0=0r-Q 



S P Q 

E 



R C ° 



s 


P Q 


-> 


o- 


E 






Clk - 


R 


■c ° 




R" 



F=0 



-=o=l> 



Q 
Q 



s 

> 


P 


Q 


R 


C 


Q 




|+ 






u 




S 


p 


Q 


> 






R 


c 


Q 



Please notice that the SR flip-flop (positive or negative edge) is never used; however, 
the gated latches connected as master and slave might be used to build more specific 



198 



Latch and flip-flop 



« 



flip-flops. Furthermore, instead of a hypothetical SR flip-flop, the JK flip-flop is used 
(see section 5.10). 

5.7 Time: setup/hold and recovery/removal 

There are two significant time intervals related to the synchronous components, which 
are the circuits that have a data input controlled by an enable or clock input line. These 
time intervals are the setup time, known with the label t sn , and the hold time, known 
with the label t h . 

Figure 5.20. Example of correct and wrong conditions, concerning the setup time 
(f su ) and the hold time (t h ) constraints. 



data 



enable/clock 



Hi 



t 



su 



th 



A 



t'SU 



Hi 



AA 



Hi 



t'SU 



th \ 



In different context, when it should be emphasized that the input data is asynchronous, 
other names are used: recovery time and removal time. 



recovery 
time 



recovery 
time 



reset 



clock 



removal 
time 



removal 
time 



Latch and flip-flop 



199 



5.8 D latch and D flip-flop 

« 

A gated SR latch or an edge triggered SR flip-flop can be connected so that the R 
input is the equal to the inverted S. This way the single input line can be called D, for 
'data', and the new circuit become a D latch or a D flip-flop. 

Figure 5.22. D latch and D flip-flop obtained from a gated SR latch or an edge 
triggered SR flip-flop. 






As for the gated SR latch and the SR flip-flop, the same consideration about the setup 
and hold time apply to the 'D' variation. But the D latch do not have invalid combi- 
nation for the input data that come form a single line. 

Figure 5.23. D latch made with NAND gates. When the E input is asserted, the 
circuit receives the data from the D input and it reproduces the same value trough 
the Q output (inverting that value at the Q output). 



data 
D>- 

E> — 

enable 




> 



> 



> Q 



> 



> 



-5* Q 



D 



Q 



Q 



200 



Latch and flip-flop 



Q 
Q 




The D latch can be implemented in more efficient ways, known as transparent latch 
and Earle latch, which appear in the following figure. Please notice that the Earle 
latch has two complementary enable inputs, E and E, which should be asserted and 
negated at the same time, to do their work properly. 

Figure 5.24. The 'transparent latch' on the left and the 'Earle latch' on the right 
side. 



transparent latch 



E>- 



D> 



E> 



)CH 



> Q 



D- 



D> 



^ Q 

E>" 



Earle latch 



Q 



The D flip-flop (edge triggered) can be implemented as master-slave, but there exists 
an alternative and more efficient circuit that triggers at the positive edge. 



Latch and flip-flop 



201 



Figure 5.25. Master- slave D flip-flop and classical positive-edge-triggered D flip- 
flop. The timing diagram is related to the second version that triggers with posi- 
tive clock edges. 



D 



Clk 



D>- 



Clk> 



Clk > 



D>- 



1 


1 






1 


> 


» — 



Q 
Q 



negative edge D flip— flop 



)o-+ 



D° — « 

> 



Vw3 



> 



wl 



> 



w2 



> 



w4 



D 

Clk 

w1 

w2 

w3 

w4 



LT 



n 



> Q 



Q 



negative edge D flip-flop 



> 



^ Q 



>— 1 > Q 



-c 



classical positive edge D flip-flop 





D Q 

> Q 













D Q 

> Q 




202 



Latch and flip-flop 



Figure 5.26. D flip-flops with initialization inputs. 



c >- 
P >- 

D>- 



C >- 



P >" 



Clk> 



D >- 



preset 



P > — 
D > f- 

Clk > — 



Clk> «► 



> 



l> 



clear 



preset 



> 



> 



> 



> 



preset 



> 



jo — l y> — ? — > q 



> Q 



> 



t > Q 



> 



clear 



• > Q 



> 



> 
> 



> Q 



)o— 1 > Q 



clear 









D F Q 

> c Q 























D F Q 

















D Q 



>_A 



Latch and flip-flop 



203 



5.9 T flip-flop 

Extending a positive edge D flip-flop it is possible to obtain a T flip-flop, where the 
T' stands for 'toggle' . When the T flip-flop receives the clock edge and the T input is 
asserted, it inverts the output values. The truth table uses the notation to indicate 
the Q output value at the time t and the notation <2(t+i) to indicate the Q output value 
at the next clock effective edge. 

Figure 5.27. Positive edge T flip-flop: timing diagram and truth table. 



Clk -[_ 
Q — 
Q 




1_ 



T 




0 




1 





when a positive edge clock signal 

is received and the T input is active, 

the output values are inverted 

The T flip-flop requires the clear or the preset input ports, because it is necessary to 
establish an initial value for the outputs. The following figure shows how to extend a 
D flip-flop with clear and preset inputs. 



« 



204 



Latch and flip-flop 



« 



Figure 5.28. A T flip-flop starting from a D flip-flop, which includes clear and 
preset inputs. 



> Q 




Q 



Clear 



5.10 JK flip-flop 

Another D flip-flop variation, recalling the SR latch, is the JK flip-flop. As for the 
T flip-flop, the truth table uses notations Q {t) and Qg+h, to specify the Q value at the 
time t or at the next effective clock edge. In short, the JK flip-flop works like the SR 
latch, where J means 'set' and K means 'reset', but when both J and K inputs are 
asserted, the output values are just reversed, like it happens with the T flip-flop. 



Latch and flip-flop 

Figure 5.29. Positive edge JK flip-flop and truth table. 



205 




J 


K 


Q tt+ 1 1 


0 


0 


O /, \ unchanged 


0 


1 


0 reset 


1 


0 


1 set 


1 


1 


Q . . output inversion 



J 

K 



Q 



J~L 



J,K=0,0 



ck jirLnnjTJirLrir^^ 



i_n n. 



J,K=0,1 



J,K=1,0 

J,K=1,1 



i_r 



J,K=0,1 



J~L 



J,K=1,0 



J,K=0,() 
J,K=1,1 

The JK flip-flop might require the clear or the preset input ports, but it is not strictly 
necessary as for the T flip-flop. Anyway, the following figure shows how to extend a 
D flip-flop with clear and preset inputs. 



206 



Latch and flip-flop 



Figure 5.30. JK flip-flop made as an extended D flip-flop with clear and preset 
inputs. 

Preset > 



• — > Q 



J>- 



Clk> 



> 




f — > Q 



Clear > 

It should be noticed that T flip-flop is just a JK one with the inputs J and K connected 
together. 

Figure 5.31. JK flip-flop adapted to work as a T one. 



Preset > 




> Q 



^ Q 



Clear > 



Latch and flip-flop 



207 



5. 1 1 Troublesome JK flip-flops 

Electronic flip-flops (D, JK, T) are currently produced with a specific technology that 
is not easily translated into common logic gates. The JK flip-flop obtained extend- 
ing the D flip-flop works correctly, but there are other circuits inside the traditional 
documentation and data sheets that if reproduced with a simulator would not work as 
expected. 

The following figure shows the circuit that can be found inside some original 7476 IC 
data sheets. This kind of circuit should be positive-edge triggered by the clock signal, 
but the timing diagram shows that it does not react this way and after the negative 
edge the circuit becomes unstable. 

Figure 5.32. JK flip-flop circuit that does not work. 



« 



Q 



P > 



K> 



Q 



<C 



<J 



A 
Ck 



208 



Latch and flip-flop 



p 

Ck 
J 
K 
Q 

Q {J 

cleared 



JUUUUUUUUUUUUUUUUUUUUl^ 



at the negative edge the flip-flop becomes unstable 



should be positive 
edge triggered, 
but it does not change 

The following figure shows a master-slave JK flip-flop (negative-edge triggered) that 
is described in the traditional documentation. This circuit might work, but it does 
not completely as expected: if the J or K input signals are negated before the clock 
negative edge, when the clock negative edge actually comes they switch the flip-flop 
anyway. 

Figure 5.33. Master- slave JK flip-flop. 



P >- 

J> 
Ck > 
K> 

C >- 



r 



L 



)o — » 



Q 



• Q 



Latch and flip-flop 



209 



C d 



Ck 1 



K 
Q 
Q 



cleared 




negative K goes 

edge down 
before 

output updated fhe dock 
negative edge 



the output is updated 
anyway 



210 Latch and flip-flop 



211 

Registers 



Chapter 6 



6.1 Simple data register 212 

6.2 Shift register 216 

6.3 Asynchronous counter with T flip-flop 217 

6.4 Synchronous T flip-flop counters 219 

6.5 Synchronous counters with D flip-flops 220 

6.6 Synchronous counters with paralel load 224 

counter 219 220 counter register 217 data register 212 register 211 shift register 216 

A register is a flip-flop array (usually D flip-flops are used) by which it is possible to 
store binary values or to build a counter. It could be possible to build registers with 
gated latches, but the edge-triggered flip-flops are more reliable for the purpose. 

The following examples use D flip-flops following the classical implementation or 
derived from that kind of circuit. Therefore, these are positive-edge triggered flip- 
flops. 

Figure 6.1. Classical D flip-flop. 



preset 



P > 



Clk> 



D > 



r > 




> Q 



* > Q 




212 



Registers 



Figure 6.2. T and JK flip-flop, derived from the D flip-flop. 



Preset >- 



« 



A k>- 



T>- 

Clk >- 

Clear >- 




Preset > 



K> [>^D^ 



J> 



Clk> 



Clear > 




The figures appearing in the following sections might call the clock line either with 
the abbreviation Clk or Ck, but the flip-flops are meant to be edge-triggered, even if 
there is not the standard triangular symbol for this purpose. 

6.1 Simple data register 

The simplest register is the one that can load a multi-bit value, storing it until the input 
lines are enabled again. In the following figure, the value stored by the register can 
be read from the output lines Q 3 .. 0 and a new value can be loaded from the input lines 
D3..0. The input value is loaded only when the input Load is asserted, otherwise the 
flip-flops just reload the previous value at every clock positive edge. 



Registers 



213 



Figure 6.3. 4-bit register: when the Load input line is asserted and a positive edge 
clock is reached, the register loads the value available from the input lines / 3 .. 0 , 
otherwise the previous stored value is just kept as it is. 



input 



D3 

V 



D2 

V 



□1 

V 



DO 

V 







Preset 




4- 


Q 




□ 


<F 


Q 




Clk 






Clear 





uu 





Preset 




Q 




D 


Q 




Clk 




Clear 





r 1 





Preset 




Q 




D 


Q 




Clk 




Clear 





Q3 



Q2 



V 
Q1 











Preset 




Q 




D 


Q 




Clk 




Clear 






-<Load 



~< Preset 



-< Clear 



-<Clk 



QO 



output 

To allow a better understanding, the following figure shows how the register works 
when it is willing to receive the input data, removing the logic that switches the data 
sources: 



214 



Registers 



D3 

V 



D2 

V 



D1 

V 



DO 

V 



"< Preset 







Preset 






Q 




D 


<F 


Q 




Clk 






Clear 





V 

Q3 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q2 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q1 





Preset 




Q 




D 


Q 




Clk 




Clear 





-< Clear 



< Clk 



V 

QO 



When the registers keeps the previous stored value, it works like the following figure: 







Preset 






Q 




D 


<F 


Q 




Clk 






Clear 





V 

Q3 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q2 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q1 





Preset 




Q 




D 


Q 




Clk 




Clear 





- < Preset 



-< Clear 



-<Clk 



V 
QO 



I should be clear that the D flip-flop inputs are switched by a multiplexer, as the 
following figure can clarify: 



Registers 



215 



Qn Dn 



Load 



Qn Dn 



0 1 



Load 



The simple data register has an important feature: it can be updated starting from the 
value that it contains already, when the positive clock edge is received. The following 
figure shows a data registers that might load a new data from a combinational circuit, 
which calculate something on the current register value: 



bo 











Preset 




Q 




□ 


5 




Clk 




Clear 





□ 











Preset 




Q 




□ 


5 




Clk 




Clear 





. □ 



-<Load 











Preset 




Q 




D 


Q 




Clk 




Clear 







Preset 




Q 




□ 


5 


Clear 


Clk 



-< Preset 



-< Clear 



-<Clk 



D3 



Q3 



D2 D1 
4-input and 4-output combinational circuit 
Q2 Q1 



DO 
QO 



The register output is connected to a combinational circuit that transforms the data 
in some unspecified way. The combinational circuit then feeds the register when the 



216 



Registers 



« 



Load input is asserted and the clock reaches the positive edge. In practice this cir- 
cuit does what could be formally written as x=f(x), or x<—f(x) if the RTN notation 
(register transfer notation) is used. 

6.2 Shift register 

The following figure shows a register that can receive a single logic value from the 
input Ds, when there is a positive edge clock signal. At this time, the first flip-flop on 
the right updates its value with the serial data obtained by the input Ds , whereas the 
second flip-flop updates itself using the previous value from the first flip-flop and the 
same thing happens to the other flip-flops. 

Figure 6.8. 4-bit shift register: when there is a positive edge clock signal, the 
input value is stored inside the first flip-flop on the right, whereas the second gets 
the old value from the first one, and so it continues up to the last flip-flop. Video: 
ogv http://www.youtube.com/watch?v=I_ncbpQnCZ4 . 




Q 


Preset 






D 


Q 




Clk 




Clear 





Q 


Preset 






D 


Q 




Clk 




Clear 





f 



Q 


Preset 






D 


Q 




Clk 




Clear 





-< Preset 



<Ds 



-< Clear 



-<Clk 



Q3 



Q2 



Q1 



QO 



A shift register, like the one that appears in the previous figure, can be extended so 
that it can load a value. In that case a Load input can be added to switch the register 
flip-flops, like the following figure shows. 



Registers 



217 



Figure 6.9. 4-bit shift register with paralel load: when the input Load is asserted 
and the clock signal reaches the positive edge, the register stores the value that is 
available at the input D3..0, otherwise, if the input Load is negated, each flip-flop 
is updated with the last value from the previous one. 



D3 

V 



D2 

V 



□ 



0 



Preset 
Q D 



Q 



Clk 



Clear 



V 

Q3 











Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q2 




DO 

V 



4 











Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q1 



□ 



-<Load 



-<Ds 



f 











Preset 




Q 




D 


Q 




Clk 




Clear 





< Preset 



-< Clear 



<Clk 



V 

QO 



6.3 Asynchronous counter with T flip-flop 

The counters are registers that increment or decrement their binary value at every 
clock pulse; the asynchronous ones contains flip-flops that are not connected to the 
same clock signal. The easiest counter is made of T flip-flops, because this kind of 
flip-flop, when the T input is asserted, inverts the output value each time it receives a 
clock pulse. The following figures show the use of cascaded T flip-flops, which means 
that each clock input is driven by the output of a previous one: that is why these are 
asynchronous counters. 



« 



218 



Registers 



Figure 6.10. 4-bit ascending asynchronous counter: the next flip-flop is driven 
by the Q output from the previous one. Video: ogv http://www.youtube.com/ 
watch ?v=-mfL6B0w9UI . 



f 



Q 


Preset 






T 


Q 


Clear 


Clk 



Y 
Q3 




Y 

Q2 



Preset 



Clk 



Clear 



Y 
Q1 



Preset 



T <- 



-v, 



dd 



- < Preset 



Clk <- 



Clk 



Clear 



-< Clear 



v 

QO 



Figure 6.11. 4-bit decreasing asynchronous counter: the next flip-flop is driven 
by the Q output from the previous one. Video: ogv http://www.youtube.com/ 
watch?v=fvhina5QEnI . 







Preset 




Q 


T 


f 


Q 


Clk 






Clear 



V 



Q3 



Q 


Preset 


T 


Q 


Clear 


Clk 



Y 



Q2 



Preset 
Q T 



Clk 



Clear 



V 



Q1 



f 



Q 


Preset 


T 


Q 


Clear 


Clk 



- < Preset 



-<Clk 



-< Clear 



V 



QO 



Asynchronous counters have the disadvantage that each binary digit is updated with 
a little delay, which is added to the next one. 



Registers 



219 



6.4 Synchronous T flip-flop counters 

Synchronous counters can be builded with T flip-flop, but in a different way from 
what is described in the previous section. However, when these counters need to be 
modified to allow a paralel binary load, D flip-flops should be used instead. 

Figure 6.12. 4-bit synchronous counter based on T flip-flops: the outputs are 
synchronous, but a little later than the clock impulse. Video: ogv http://www. 
youtube.com/watch?v=Nh5CzRopNdY . 



■O 



f 



V 

Q3 



Q 


Preset 








T 


Q 






Clk 




Clear 







Q 


Preset 


T 


4- 






<^ 


Q 






Clk 






Clear 





V 

Q2 



-< Preset 





Q 


Preset 




+■ 






T 


«r 


Q 






Clk 






Clear 





t 

Q1 









Q 


Preset 






T 


Q 




Clk 




Clear 





"dd 



-<Clk 



-< Clear 



« 



V 

QO 



delay after the clock positive edge 



Clk 

QO 

Q1 

Q2 

Q3 



0 1 



2 3 



718 



10 



1112 



13 



14 



15 



The synchronous counter requires that the T input of the first flip-flop remains always 
asserted. However, controlling that input it is possible to pause the counting process, 
without clearing the current value. Therefore it is possible to add an enable input, 
controlling the T input of the first flip-flop, as the following figure shows in red. 



220 



Registers 



Figure 6.13. 4-bit synchronous counter with enable input (En). 



f 









Q 


Preset 






T 


Q 




Clk 




Clear 





v 

Q3 





Q 


Preset 




4- 






T 




Q 






Clk 






Clear 





V 

Q2 





Q 


Preset 




4- 






T 


«f 


Q 






Clk 






Clear 





V 

Q1 



-< Preset 



Q 


Preset 








T 


Q 






Clk 




Clear 





-<En 



-<Clk 



-< Clear 



V 

Q0 



To obtain a decreasing counter it is enough to invert the outputs of each T flip-flop 
involved. 

Figure 6.14. 4-bit decreasing synchronous counter, with enable input. 





Preset 




Q 




T 


Q 


Clear 


Clk 



■o 





Preset 




Q 




T 


Q 


Clear 


Clk 




-< Preset 





Preset 




Q 






T 


Q 






Clk 


Clear 





-<En 
-<Clk 



-< Clear 



V 

Q0 



6.5 Synchronous counters with D flip-flops 

It is generally more convenient to build synchronous counter using D flip-flops, as 
they can be easily extended to allow a paralel binary load. This section shows only 
equivalent examples of the previous one (with D flip-flops), but the following section 
is then related to the paralel load. 



Registers 



221 



Figure 6.15. 4-bit ascending synchronous counter, with enable input, made of 
D flip-flops. 

a= 



-o 



-o 



0 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 
Q3 



■o 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q2 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q1 



<En 





Preset 




Q 




D 


Q 




Clk 




Clear 





-< Preset 



<Clk 



-< Clear 



V 
QO 



Figure 6.16. 4-bit decreasing synchronous counter, with enable input, made of 
D flip-flops. 

0= 



-(3= 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 
Q3 



1 



■o 





Preset 




Q 




D 


Q 




Clk 




Clear 





v 

Q2 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q1 



<En 



0 



v 





Preset 




Q 




D 


Q 




Clk 




Clear 





-< Preset 



-<Clk 



-< Clear 



V 
QO 



222 



Registers 



Figure 6.17. Alternative 4-bit decreasing synchronous counter, with enable input, 
made of D flip-flops. 



■o 



Preset 



Clk 



Clear 



V 

Q3 



■o 



0 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q2 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q1 



<En 





Preset 




Q 




D 


Q 




Clk 




Clear 





"< Preset 



-< Clk 



-< Clear 



V 

QO 



It is important to understand the logic added to the D flip-flops, which is made of 
simple half-adders or half-subtractors. 

Figure 6.18. The ascending synchronous counter contains a half-adder. 



0 







Preset 




+■ 


Q 




D 


♦f 


Q 




Clk 






Clear 





-<En 



iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii 



-< Preset 




"'■■iiluuinii,,, 1MI| 



<Clk 



-< Clear 



V 

Q 



-<En 



A 


B 


Co 


HA 




S 



-< Preset 















Preset 




<- 


Q 




D 


*{ 


Q 




Clk 






Clear 





-<Clk 



-< Clear 



Q 



Registers 

Figure 6.19. The decreasing synchronous counter contains a half-subtractor. 

KD= 



223 



0 







Preset 




<- 


Q 




D 


♦f 


Q 




Clk 






Clear 





-<En 



llllllllllllllllllllllllllllllllllllllllllllllllll 



-< Preset 




'""'"iiiiiiiiiiiiiiii,,,, 



-<Clk 



-< Clear 



'"" » ii i,,,,^. 



-<En 



S M 
Bo H S 
D 



Preset 
Q D 



-< Preset 



Clk 



-<Clk 



Clear 



-< Clear 



V 

Q Q 

The D flip-flops might be represented in a compact, paralel draw, where the ports D, 
Q and Q are bit vectors. In that case also the counter can be shown in a more compact 
way. The following figure shows the use of a full-adder and a full- subtrac tor, because 
they allow to follow the concept in an easier and immediate way. 



Figure 6.20. Compact representations. 

~Z4 



4 

7^ 



Co 



+ 



<En 



Preset 

V 



/ 4 



V 



/a 



Preset 



Q 
Q 



D 
Clk 



Clear 



4 

77^ 



la 



-<Clk 



A 



Clear 



14 



<En 



Bo 



Preset 

V 



/4 




iBi 



-<Clk 



V 



A 



Q 



Q 



Clear 

incrementing counter decrementing counter 

The compact representation allows to understand how to extend and possibly to sim- 



224 



Registers 



« 



plify the logic. The following example replaces the enable input with the value to be 
added at each clock signal, value that might be either positive or negative, or even 
zero if no change should be applied. 

Figure 6.21. More general counter with variable increment. 

4 



/ 



V 



Q 



4 



Co < 



+ 



<lnc 



<Ci 



Preset 

V 




4 



<Clk 



A 
Clear 



6.6 Synchronous counters with paralel load 

The counter is complete only if it allows the paralel data load. The following figures 
show counters based on D flip-flops, allowing the paralel data load. 



Registers 



225 



Figure 6.22. 4-bit synchronous counter with paralel data load: the input Load 
allows to load the value received by the inputs D 3 .. 0 into the flip-flops; otherwise, 
if the Load input is negated, the input En allows to increment or keep unchanged 
the previous value stored inside the register. 



D3 

V 



D2 

V 



D1 

V 



DO 

V 



■o 



0 

_Q_ 



■o 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q3 



V 

_Q_ 



■o 





Preset 




Q 




D 


Q 




Clk 




Clear 





Y 

02 



-o 



0 





Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q1 



_Q_ 



-<En 





Preset 




Q 




D 


Q 




Clk 




Clear 





-<Load 
- < Preset 



-<Clk 



-< Clear 



V 
QO 



226 



Registers 



Figure 6.23. 4-bit synchronous decreasing counter with paralel load, similar to 
the previous figure. 



D3 

V 



y 

Q 1 











Preset 




Q 




D 


Q 




Clk 




Clear 





D2 

V 



D1 

V 



DO 

V 



y 

Q 1 











Preset 




Q 




D 


Q 




Clk 




Clear 





V 

Q2 



y 

Q 1 





Preset 




Q 




D 


Q 


Clear 


Clk 



V 

Q1 



y 

_Q_ 











Preset 




Q 




D 


Q 




Clk 




Clear 





V 

QO 



-<En 



-< Load 
- < Preset 



-< Clk 



-< Clear 



Registers 



227 



Figure 6.24. 4-bit synchronous increasing and decreasing counter: the input / 
allows to select if the counter should increase or decrease. 



D3 

V 



D2 

V 



D1 

V 



DO 

V 







Preset 




Q 




D 


5 




Clk 




Clear 





V 

Q3 



y 

_Q_ 





Preset 




Q 




□ 


Q 


Clear 


Clk 



z 



V 
Q2 



V 

Q 1 











Preset 




Q 




□ 


5 




Clk 




Clear 





V 

Q 1 











Preset 




Q 




□ 


5 




Clk 




Clear 





V 
QO 



-<En 
-<f 

f=0: inc 
f=1 : dec 



< Preset 



-<Clk 



-< Clear 



228 



Registers 



Figure 6.25. 4-bit synchronous counter with paralel load: this is a simpler solu- 
tion, where the increment value is free and might be positive, negative or zero. 



4 



4 Z <lnc 



CO <r 



Clear 



-<Ci 







4 




7 4 


1 7^ 


/ 





<D 




<Load 



Q 



229 



Chapter 



Bus and control unit 



7.1 



Tri-state buffer 



229 



7.2 



Hardcoded bus control unit 



232 



7.3 



Microcode 



236 



bus 229 microcode 236 tri-state buffer 229 

Registers and combinational circuits are often grouped together, joining a set of con- 
nections (wires). This set of connections is what is known as bus. A bus where dif- 
ferent components have the ability to write to and read from is usually a data bus, 
because it is used to exchange data between the components; however, it should be 
noticed that only one component at a time should be allowed to write to the bus, 
whereas for reading there is no limitation. 

7.1 Tri-state buffer 

A data bus can be implemented with a multiplexer or with tri-state buffers, which 
are components similar to buffers or inverters (depending on the type), but with an 
additional input that is used either to enable the output or to isolate it. The following 
figure shows the tri-state buffer compared to a traditional switch: 



The tri-state buffers, or the multiplexer, are necessary to control the bus writing. The 
tri-state buffer method is simpler and cheaper than the multiplexer more simple and 
cheaper, because the multiplexer would require more logic gates and a longer propa- 
gation delay. 

The following figures show the adaptation of a simple data register, using a tri-state 
buffer to connect it to a bus; then this kind of register is shown connected with others 
on a data bus, controlled by a control bus. 




0 = isolation 



0 = open circuit 

1 = closed circuit 



1 = buffer 



230 



Bus and control unit 



Figure 7.2. Simple data register adaptation for a data bus. 



n 











Preset 




Q 




D 


Q 




Clk 




Clear 





V 











Preset 




Q 




D 


Q 




Clk 




Clear 





1 



v- 











Preset 




Q 




D 


Q 




Clk 




Clear 





0 

Bus3 



v- 



0 











Preset 




Q 




D 


Q 




Clk 




Clear 





0 

Bus2 



v- 



o 

Bus1 



0 

BusO 



-<bus_read 
(Load) 



-< Preset 



-< Clear 



-<Clk 



-<bus write 



Bus and control unit 



231 



Figure 7.3. Simplified diagrams for the same register adaptation. The input 
bus_read, or br, is used to load and store the bus value into the register, whereas 
the input bus_write, or bw, allows the register to write its stored value to the bus. 



Clk>- 



13 


12 


11 


10 


Clk 








Load 


Q3 


02 


Q1 


QO 



v- 



"<bus read 



Clk> 



0 

Bus3 



"<bus write 




<br 



<bw 



Bus2 



Bus1 



0 

BusO 



Here are used the definitions "bus read" and "bus write", to identify respectively the 
actions to load a value from the bus and to put a value to the bus; however, some more 
formal documentation, when referring to registers, prefer the definitions "load" and 
"enable" instead (because the register loads data or is enabled to write its data). 



232 



Bus and control unit 



Figure 7.4. Different components connected to the bus: the control inputs used 
to enable reading or writing the bus, together with other potential control inputs, 
are connected to a secondary bus (the control bus). The second draw shows an 
alternative way to represent the connections to the control bus, picking a wire at 
a time. 



Con>" 



Clk>— 
bus O- 



br 




bw 


Clk 


bus 






br 




bw 


Clk 


bus 





br 




bw 


Clk 


bus 






« 



7.2 Hardcoded bus control unit 

To direct properly the data bus usage it is necessary a control unit, which should 
be responsible to mark the phases of every process that is to be applied. To under- 
stand the problem the following diagram is used (which is already appeared in the 
previous section), where three components communicate through a data bus, under 
the direction of a control bus: for these components are considered only data transfer 
operations. 



Bus and control unit 



233 



Figure 7.5. Three components communicating through a data bus. 



control bus 



Con> 



Clk> 




data bus 



To mark the operation steps, the control unit needs a counter. There are two main 
types of control units, the first one is hardcoded, the second is microcoded. The 
hardcoded control unit requires a shift counter, which can be implemented as the 
following figure shows. What should be noticed reading the timing diagram is that 
the output control lines are active (asserted) before the clock impulse used to drive 
the data bus components: to obtain this result, the clock pulse used by the counter is 
inverted. 



234 



Bus and control unit 



Figure 7.6. Shift counter used by the control unit: the clock signal is inverted, 
so that the output lines T n are already active when clock positive margin 
reaches the data bus components. Video: ogv http://www.youtube.com/watch?v= 
vXco4E4SNTo . 



4" 




V, 



dd 




-v, 



dd 



-<r 



-<Clk 



-< Clear 



cik ^^^^^^^^^^TL^^^^OT 







/ 


7 2 



dec 



-v, 



dd 



V 



T3 



0 



v 



12 



V 
T1 



TO 



TO 










































T1 




































































T3 1 











































































The hardcoded control unit should put together a function decoder with the shift regis- 
ter outputs. For example, the function// of the diagram should do the following: copy 
A to B, then copy B to C: the decoder activates the second line (labeled fl), then, 
with some AND gates the outputs Aw and Br are activated when the shift counter has 
the To output active, then, the same way, the outputs Bw and Cr are activated when 
the shift counter has the T\ output active. The outputs Aw, Br, Bw and Cr, activated 
at the proper time, following the shift counter direction, would enable the registers 
read- write, allowing the programmed data transfer. The control unit implementation 
that appears in the following figure is extremely simplified and the T 2 time is not 
even used; however, the time T 3 is used instead to stop the clock signal related to the 
control unit itself, which should be cleared to be able to accept a new command from 
the input/. 



Bus and control unit 



235 



Figure 7.7. Control unit: only four simple functions are available, for which two 
times are sufficient; therefore the time T 2 is unused and the time T 3 locks the 
control unit until the Run input is cleared and reactivated. Video: ogv http:// 
www.youtube.com/watch ?v=r-DZgjy-yaO . 



Clk 

V 



shift counter 
Clk Clear 



-< Run 




fO: B<— A 
f 1 : c<— B<— A 
f2: C< — B 
f3: A<— C<— B 



T1 

12: not used 



Con 



236 



Bus and control unit 



« 



Figure 7.8. Control unit connected to the components that should drive. Video: 
ogv http://www.youtube.com/watch?v=kpET2kEcUIo . 



f fO:B:=A 
f1:C:=B:=A 




7.3 Microcode 

The implementation of a hardcoded control unit is a complex work. For that reason is 
usually preferable a ROM memory (read only), divided into two parts: the map and 
the microcode. The two parts of the memory should be see as two tables: the first one 
translates the desired function into an address to the second table, where the code for 
the related procedure starts. Please see the following figure, where on the left there is 
the control unit diagram and on the right there is the counter implementation. 



Bus and control unit 



237 



Figure 7.9. Control unit implemented with ROM memories: on the left appears 
the control unit block diagram and on the right there is the detailed four-bit 
counter (the counter can be incremented or can load a new value). Video: ogv 
http://www.youtube. com/watch ?v=mBGhNP3 Uujs . 



% 



mO 



counter 



start 



Clk>- 



— >- 



jump to 

instruction 

execution 



ml 



Run 



CON 



The two ROM memories are named, respectively, mO and ml . In the following figure 
is shown the content of these memories, using tables, associating the memory address 
input (A) with the corresponding value that is returned from the memory data output 
(D). The mO memory of these examples uses only two bits for the addresses, which 
correspond to the function requested to the control unit that is known as operation 
code or opcode, whereas the data output has a 4-bit range, which in turn is the address 
for the ml memory (the microcode). 



238 



Bus and control unit 



Figure 7.10. Memory contents and links between them. 



m 



o 



m 



fo 



address 


content 


0 


0001 


(1) - 


1 


0011 


(3) - 


2 


0110 


(6) x 


3 


1000 


(8) \ 



address 


content 


0 


000000010 


load counter 


w 1 


000110000 


B < — A 


2 


000000111 


load zero, stop clock 


^ 3 


000110000 


B< — A 


4 


011000000 


C< — B 


5 


000000111 


load zero, stop clock 


X 6 


011000000 


C< — B 


X 7 


000000111 


load zero, stop clock 


8 


011000000 


C< — B 


9 


100001000 


A < — C 


10 


000000111 


load zero, stop clock 



The output from the mO memory is assigned to a counter; the counter output is used 
to access to the ml memory; the ml memory output is the microcode word used to 
control the bus and the same control unit itself. To allow a better understanding of the 
process, the various steps are listed below, assuming that the function/i (opcode) has 
been requested. 

1. When the system is started, the Run input is equal to 0 (zero), which involves 
the counter reset to zero. As the counter starts from zero, from the ml memory 
is selected the value 0000000 10 2 , which is the initial microcode word. The active 
bit of the microcode word is used to request the counter to load the value that 
comes from the memory mO (001 1 2 ), which produces that value corresponding to 
the address that represent the input function (f x = 01 2 ). 

2. Activating the Run input, at the clock negative edge (the global clock is inverted 
for the control unit) the counter loads the address from the mO memory (001 1 2 ) 
and offers the same value to the ml memory as an address. The ml memory 
produces the value 000110000 2 as the new microcode word, which corresponds 
to the request to copy the register A to B. 

3. At the next clock negative edge the counter is incremented, selecting from the 
ml memory the address 0 1 00 2 which gives the value 011000000 2 , which in turn 



Bus and control unit 



239 



corresponds to the request to copy the B content into C. 

4. At the next clock negative edge the counter is incremented again, selecting from 
ml the value corresponding to the address OIOI2, which is 0000001 II2, which in 
turn corresponds to the request to clear the counter, loading the fixed value 0000 2 , 
and to suspend the clock signal received by the control unit. 



At this point, the execution cycle of a function is finished, but to start another cycle 
after another function is selected, it is necessary to disable and enable again the input 
Run. 

Figure 7.11. Connection between the control unit and the other data bus compo- 
nents: the first three lines from the control bus are used inside the control unit 
itself and are not useful to drive the data bus modules. 

I f0:B<— A 
f1 : C<— B<— A 



Run >- 



/ 2 



f2: C<— B 
f3: A<— C<— B 



f 

Run CTRL CON 
Clk 



Clk>- 




Clk 



B 



bus 




The ROM memories that are used in a control unit can be coded with the help of tools 
that allow a symbolic notation. For example, TKGate has a special compiler that 
produces map and microcode image files, starting from a single source file. Please 
notice that the function requested to the control unit are defined as labels inside the 
opcode map memory. The following source listing is compatible with the examples 
of this section. 



240 



Bus and control unit 



Listing 7.12. Opcode and microcode following the TKGate 2 syntax. 



// MEMORIES: 

map bank [1:0] 

microcode bank [8:0] 
// 



mO; 
ml ; 



// MICROCODE WORD FIELDS 

field ctrl_start [ 0 ] ; 

field ctrl_load [ 1 ] ; 

field stop[2] 

field a_br [ 3 ] 

field a_bw[4] 

field b_b r [ 5 ] 

field b_bw[6] 

field c_b r [ 7 ] 

field c_bw[8] 
// 



// set the address to 0 
// load the counter 
// stop the clock 
// A < — bus 
// A — > bus 
// B < — bus 
// B — > bus 
// C < — bus 
// C — > bus 



// FUNCTIONS 

op fO { 

map f 0 : 0 ; 
+0 [7 : 0] =0; 

I; 

op fl { 

map f 1 : 1 ; 
+0 [7 : 0] =1; 

}; 

op f 2 { 

map f 2 : 2 ; 
+0 [7 : 0] =2; 

}; 

op f 3 { 

map f 3 : 3 ; 
+0 [7 : 0] =3; 

}; 

// 



= OPCODES. 



Bus and control unit 



241 



// MICROCODE ' 


















begin microcode 


@ 0 
















load : 


















p1"t1 1 oa (i : 

V l . J_ _l_ _l_ OL \_A J 








// 


CNT 


<- 




TBL [f] 


f 0 : 


















b_br a_bw; 








// 


B <- 




A 




Ct T 1 S t r3 T1" 


ct r 1 


load 


s t op } 


// 


CNT 


<- 




o 


f 1 : 


















b_br a_bw; 








// 


B <- 


— 


A 




c_br b_bw; 








// 


C <- 




B 




ft T 1 S t Pi "ft 


ct r 1 


load 


s t op } 


// 


CNT 


<- 




o 


f2 : 


















c_br b_bw; 








// 


C <- 




B 




ft T 1 S1" r5 T1" 


ct r 1 


load 


s t op } 


// 


CNT 


<- 




o 


f 3 : 


















c_br b_bw; 








// 


C <- 


— 


B 




a_br c_bw; 








// 


A <- 




C 




ctrl start 


ct r 1 


load 


stop ; 


// 


CNT 


<- 




0 


end 



















The map memory content is organized in opcodes: the operation code is the address in 
which is located inside the map memory; for example, the function f 2 has the opcode 
2 (10 2 ): 

op f 2 { 

map f 2 : 2 ; 
+0 [7 : 0] =2; 

Jl 

The figure that connects the mO and ml memories appears again below, with the 
addition of other details, to conclude the topic. 



242 



Bus and control unit 



Figure 7.14. Map (opcodes) and microcode. 



opcode 
0 map 



/. 
A 
A 
f. 



address 


content 


0 


0001 


(1) ~~ 


1 


0011 


(3) - 


2 


0110 


(6) x 


3 


1000 


(8) \ 




ni y 


microcode 




address 


content 


0 


000000010 


load counter 


1 


000110000 


B< — A 


2 


000000111 


load zero, stop clock 


3 


000110000 


B < — A 


4 


011000000 


C< — B 


5 


000000111 


load zero, stop clock 


6 


011000000 


C< — B 


7 


000000111 


load zero, stop clock 


8 


011000000 


C< — B 


9 


100001000 


A <— C 


10 


000000111 


load zero, stop clock 



Traditional logic integrated circuits 



Data distributors or demultiplexers 244 

74138 3-to-8 data distributor or demultiplexer 244 

74139 dual 2-to-4 data distributor or demultiplexer 247 

74154 4-to-16 data distributor or demultiplexer 250 

74238 3-to-8 data distributor or demultiplexer 254 

Data selectors or multiplexers 257 

74150 l-of-16 data selector or multiplexer 257 

74151 l-of-8 data selector or multiplexer 262 

74153 dual l-of-4 data selector or multiplexer 265 

74157 quad l-of-2 data selector or multiplexer 268 

Special circuits 271 

74148 8-to-3 priority encoder 271 

Arithmetic units 275 

7483 4-bit binary full-adder 275 

7485 4-bit magnitude comparator 278 

74181 'a' ALU 281 

74181 'b' ALU 287 

74182 carry lookahead generator 291 

74381 4-bit ALU 293 

74382 4-bit ALU 297 



74138 244 74139 247 74148 271 74150 257 74151 262 74153 265 74154 250 74157 
268 74181 281 287 74182 291 74238 254 74381 293 74382 297 7483 275 7485 278 



243 



Data distributors or demultiplexers 



« 



« 



74138 3-to-8 data distributor or demultiplexer 



74138 truth table. 



2 


l 




A? 


A, 


An 


1 7 


V. Vr Y, Yo Y. Y, y„ 

-* 6 -* 5 1 A 1 3 -* 2 -* 1 ■* 0 


V 

/V 


V 
yv 


1 

1 


V 

A 


V 


x 






X 

/V 


1 

i 


n 


V 

/V 


x 

/V 


x 




1111111 


n 




V 


V 


x 


x 




1111111 




o 


o 


0 


o 

V./ 


o 

V./ 


1 


1111110 




0 


0 


0 


0 


1 








0 


0 


0 


l 


0 








0 


0 


0 


l 


1 








0 


0 


1 


0 


0 








0 


0 


1 


0 


1 








0 


0 


1 


1 


0 




0 111111 




0 


0 


1 


1 


1 


0 


1111111 



(1) 


-► 


AO 


@ 


Vcc 




(16) 


(2) 


-*■ 


A1 




YO 




(15) 


(3) 


-* 


A2 




Y1 




(14) 


(4) 


-* 


E0~ 




Y2 


■+ 


(13) 


(5) 






i74138 








-* 


E1~ 




Y3 


-► 


(12) 


(6) 


-+ 


E2 




Y4 




(11) 


(7) 


4- 


Y7 




Y5 




(10) 


(8) 


-* 


GND 




Y6 




(9) 



TOP VIEW 



A>" 



> YO 
- Y1 
' Y2 

> Y3 



> Y4 
-3- Y5 
-> Y6 

> Y7 



A 
E0 



_A 
E1 



A 
E2 



244 



E0~ >" 

eT >- 

E2 >" 



A> 



> 



> 



> 



> 



> 



> 



> 



Y 



74138 Verilog code. 



module h74138 (_Y, A, 


EO, _E1, E2) ; 




input [2:0] A; 








input _E0, 


_E1, E2; 








output [7 


0] _Y; 








// 










f unct ion 


[7:0] f74138 


(input [2 


:0] 


A, input _E0, 






input _E1, 


input E2 ) ; 


if (_E0 


== 0 && _E1 


== 0 && E2 = 


= 1) 


begin 










case (A) 








0 


f74138 = 8 


'blllllllO, 






1 


f74138 = 8 


f bllllllOl, 






2 


f74138 = 8 


'blllllOll, 






3 


f74138 = 8 


'bllllOlll, 






4 


f74138 = 8 


'blllOllll, 






5 


f74138 = 8 


f bllOlllll, 






6 


f74138 = 8 


'blOllllll, 







245 



7: f74138 = 8'b01111111; 
endcase 
end 
else 
begin 

f74138 = 8'bllllllll; 
end 
endf unction 
// 

assign #8 _Y = f74138 (A, _E0, _E1, E2) ; 
endmodule 



246 



74139 dual 2-to-4 data distributor or demultiplexer 



« 



One half 74139 truth table. 



E 


A\ 


A 0 


Y 3 


Y 2 


Yi 


Y 0 


1 


X 


X 


1 


1 


1 


1 


0 


0 


0 


1 


1 


1 


0 


0 


0 


1 


1 


1 


0 


1 


0 


1 


0 


1 


0 


1 


1 


0 


1 


1 


0 


1 


1 


1 



(1) 


-► 


Ea 


@ Vcc 


4- 


(16) 


(2) 


-*■ 


AaO 


Eb~ 


4- 


(15) 


(3) 


-► 


Aa1 


AbO 


4- 


(14) 


(4) 


4- 


YaO 


Ab1 


4- 


(13) 








i74139 






(5) 


<- 


Yal 


YbO 


-¥ 


(12) 


(6) 


4- 


Ya2 


Ybl 


-* 


(11) 


(7) 


4- 


Ya3 


Yb2 


-* 


(10) 


(8) 


-+ 


GND 


Yb3 


-*■ 


(9) 






TOP VIEW 







Aa>^ 



Ab>- 



2 



0 


0 


:> 


YaO 




0 


> 


Yal 




0 


— > 


Ya2 


3 


0 


:> 


Ya3 



Ea 



0 



_A 
Eb 



> YbO 
Ybl 

> Yb2 

> Yb3 



247 




^ Ya 



^ Yb 



74139 Verilog code. 



module h74139 (_Ya, _Yb, 


Aa, Ab, 


_Ea, 


_Eb) ; 


input [1:0] Aa, Ab; 








input _Ea, _Eb; 








output [3:0] _Ya, _Yb; 








// 








function [3:0] f74139 


(input [1 


:0] 


A, input _E) ; 


if (_E == 0) 








begin 








case (A) 








0: f74139 = 4' 


blllO; 







248 



1- f74139 = 4'bll01. 




2 • f 74139 = 4' blOll : 




3 • f 74139 = 4' bOlll . 




p n ci f r sp 




end 




S 1 S G 




hpni n 




f741^Q = 4 ' "hi 1 1 1 • 




end. 




endfunction 




// 




assign #8 _Ya = f74139 (Aa, 


Ea) ; 


assign #8 _Yb = f74139 (Ab, 


_Eb) ; 


endmodule 





249 



74154 4-to-16 data distributor or demultiplexer 

« 



74154 truth table. 



E\ Eq 


A 3 


A 2 


Ai 


A 0 








Y\4 Y 13 Y \2 Fn Y io Yg Yq Y(, F5 F4 F3 Y 2 Y \ F[ 


1 1 


X 


X 


X 


X 






1 0 


X 


X 


X 


X 


1 


111111111111111 


0 1 


X 


X 


X 


X 


1 


111111111111111 


1 1 


0 


0 


0 


0 


1 


111111111111110 


1 1 


0 


0 


0 


1 


1 


11111111111110 1 


1 1 


0 


0 


1 


0 


1 


1111111111110 11 


1 1 


0 


0 


1 


1 




111111111110 111 


1 1 


0 


1 


0 


0 


l 


11111111110 1111 


1 1 


0 


1 


0 


1 


l 


1111111110 11111 


1 1 


0 


1 


1 


0 


l 


111111110 111111 


1 1 


0 


1 


1 


1 




11111110 1111111 


1 1 


1 


0 


0 


0 


{ 


1111110 11111111 


1 1 


1 


0 


0 


1 


l 


111110 111111111 


1 1 


1 


o 


1 

1 






11110 1111111111 


1 1 


1 


0 


1 


l 






1 1 


1 


1 


0 


0 






1 1 


1 


1 


0 


1 






1 1 


1 


1 


1 


0 




0 11111111111111 


1 1 


1 


1 


1 


1 


0 


111111111111111 



250 



(1) 


<- 


Y0 


@ 


Vcc 


<- 


(24) 


(2) 


<- 


Y1 




AO 


<^ 


(23) 


(3) 


«- 


Y2 




A1 


*■ 


(22) 


(4) 


<- 


Y3 




A2 


4- 


(21) 


(5) 


<- 


Y4 




A3 


<- 


(20) 


(6) 


<- 


Y5 


i74154 


El 


«- 


(19) 


(7) 


<- 


Y6 




EO 


<- 


(18) 


(8) 


<- 


Y7 




Y15 


-f 


(17) 


(9) 


<- 


Y8 




Y14 




(16) 


(10) 


<- 


Y9 




Y13 




(15) 


(11) 


<- 


yTo 




Y12 


-> 


(14) 


(12) 


» 


GND 




Y11 


-> 


(13) 




251 



A>- 



4 



EO > 



E1 >- 




t>- 
!p— 
!p— 
!p— 
=p— 
p— 
p— 
p— 
p— 
p— 
p— 
p— 
p— 
p— 



_9 
JO 
11 
12 
13 
14 
15 



-s* Y 



74154 Verilog code. 



module h74154 (_Y, A, _E0, _E1) ; 




input [3:0] A; 




input _E0, _E1; 




output [15:0] _Y; 




// 




function [15:0] f74154 (input 


[3:0] A, 


input 


_E0, input _E1) ; 


if (_E0 == 0 && _E1 == 0) 




begin 




case (A) 





252 



0 : 


f 74 154 




16'blllllllllllllllO; 

_1_ W _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ V_/ / 


1 : 


f 74 154 




16'bllllllllllllll01; 

_l_ v_/ _K_y _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ V_y _1_ g 


2 : 


f 74 154 




16'blllllllllllll011; 


3 : 


f 74 154 




16'bllllllllllll0111; 

_i_ _k_/ _i_ _i_ _i_ _i_ _i_ _i_ _i_ _i_ _i_ _i_ _i_ _i_ \j _i_ _i_ _i_ / 


4 : 


f 74 154 




16'blllllllllll01111- 

_l_ \J _1_ _L _L _1_ _1_ _1_ _1_ _1_ _l_ _l_ _L \J _l_ _l_ _l_ _l_ w 


5 : 


f 74 154 




16'bllllllllll011111; 

_l_ v_/ _K_y _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ \J _1_ _1_ _1_ _1_ _1_ g 


6 : 


f 74 154 




16'blllllllll0111111; 


7 : 


f 74 154 




16'bllllllll01111111; 

_1_ V_/ _k_/ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ V_/ _1_ _1_ _1_ _1_ _i_ _1_ _1_ / 


8 : 


f 74 154 




16'blllllll011111111; 


9 : 


f 74 154 




16'bllllll0111111111; 


10 : 


f 74 154 




16'blllll01111111111; 

_1_ \J _1_ _1_ _1_ _1_ _1_ \J _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ g 


11 : 


f 74 154 




16'bllll011111111111; 

_l_ \J _i_ _i_ _i_ _i_ v_/ _l_ _l_ _l_ _l_ _l_ _l_ _l_ _l_ _l_ _l_ _l_ / 


12 : 


f 74 154 




16'blll0111111111111; 

_l_ v_/ _K_/ _1_ _1_ _1_ \J _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ _1_ / 


13 • 


f 74 154 




16'bllOlllllllllllll' 

_l_ \J U _l_ _l_ \J _l_ _l_ _l_ _l_ _l_ _l_ _l_ _l_ _l_ _l_ _l_ _L _l_ r 


14 : 


f74154 




l/^/L^lf^-ll 11 111 1111111 . 

loblOllllllllllllll; 


15 : 


f74154 




16'b0111111111111111; 


endcase 







end 



else 
begin 

f74154 = 16'bllllllllllllllll; 
end 
endf unction 
// 

assign #8 _Y = f74154 (A, _E0, _E1); 
endmodule 



253 



« 



74238 3-to-8 data distributor or demultiplexer 



74238 truth table. 



E 2 


E l 


E 0 


A 2 


Ai 


A 0 


F 7 


Y 6 


Y 5 


Y 4 


Y 3 


Y 2 


Y\ 


Y 0 


X 


X 


1 


X 


X 


X 


0 


0 


0 


0 


0 


0 


0 


0 


X 


1 


0 


X 


X 


X 


0 


0 


0 


0 


0 


0 


0 


0 


0 


X 


X 


X 


X 


X 


0 


0 


0 


0 


0 


0 


0 


0 


1 


0 


0 


0 


0 


0 


0 


0 


0 


0 


0 


0 


0 


1 


1 


0 


0 


0 


0 


1 


0 


0 


0 


0 


0 


0 


1 


0 


1 


0 


0 


0 


1 


0 


0 


0 


0 


0 


0 


1 


0 


0 




0 


0 


0 


1 


1 


0 


0 


0 


0 


1 


0 


0 


0 




0 


0 


1 


0 


0 


0 


0 


0 


1 


0 


0 


0 


0 




0 


0 


1 


0 


1 


0 


0 


1 


0 


0 


0 


0 


0 




0 


0 


1 


1 


0 


0 


1 


0 


0 


0 


0 


0 


0 




0 


0 


1 


1 


1 


1 


0 


0 


0 


0 


0 


0 


0 



(1) 




AO v - 


Vcc 


*■ 


(16) 


(2) 




A1 


YO 


■+ 


(15) 


(3) 


■+ 


A2 


Y1 


-► 


(14) 


(4) 


-¥ 


E0~ 


Y2 


■+ 


(13) 


(5) 




i74238 








-¥ 


E1~ 


Y3 


-*■ 


(12) 


(6) 


-+ 


E2 


Y4 


-* 


(11) 


(7) 




Y7 


Y5 


■+ 


(10) 


(8) 




GND 


Y6 


-* 


(9) 



TOP VIEW 



A>" 



E0 



0 



E1 



A 
E2 



> YO 
> Y1 

Y2 

> Y3 



> Y4 

> Y5 

> Y6 

> Y7 



254 



E0~ > 
ET > 
E2 >" 



3 



1> 



74238 Verilog code. 



Y 



module h74238 (Y, A, 


EO, _E1, E2 ) ; 




input [2:0] A; 








input _E0, 


_E1, E2; 








output [7 


0] Y; 








// 










f unct ion 


[7:0] f7423 


8 (input [2 


:0] 


A, 






input _E0, 


input _E1, input E2); 


if (_E0 


== 0 && _E1 == 0 && E2 = 


= 1) 


begin 










case (A) 








0 


f74238 = 


8'b00000001, 






1 


f74238 = 


8'bOOOOOOlO, 






2 


f74238 = 


8'bOOOOOlOO, 






3 


f74238 = 


8'b00001000, 






4 


f74238 = 


8'bOOOlOOOO, 






5 


f74238 = 


8'bOOlOOOOO, 






6 


f74238 = 


8'b01000000, 







255 



7: f74238 = 8' blOOOOOOO; 
endcase 
end 
else 
begin 

f74238 = 8'b00000000; 
end 
endf unction 
// 

assign #8 Y = f74238 (A, _E0, _E1, E2); 
endmodule 



256 



Data selectors or multiplexers 

74150 1 -of- 1 6 data selector or multiplexer 



74150 truth table. 



E 


D 


5 D 


aD 


13 £ 


iD\ 


D 


0^9 


D s 


#7 


D 6 


D 5 


D 4 


D 3 


D 2 


D, 


#0 


A 3 


A 2 


A, 


A 0 


Y 


0 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


0 


0 


0 


0 


0 


1 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


0 


0 


0 


0 


0 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


0 


X 


0 


0 


0 


1 


1 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


X 


0 


0 


0 


1 


0 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


0 


X 


X 


0 


0 


1 


0 


1 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


X 


X 


0 


0 


1 


0 


0 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


0 


X 


X 


X 


0 


0 


1 


1 


1 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


X 


X 


X 


0 


0 


1 


1 


0 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


0 


X 


X 


X 


X 


0 


1 


0 


0 


1 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


X 


X 


X 


X 


0 


1 


0 


0 


0 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


0 


X 


X 


X 


X 


X 


0 


1 


0 


1 


1 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


X 


X 


X 


X 


X 


0 


1 


0 


1 


0 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


0 


X 


X 


X 


X 


X 


X 


0 


1 


1 


0 


1 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


X 


X 


X 


X 


X 


X 


0 


1 


1 


0 


0 


1 


X 


X 


X 


X 


X 


X 


X 


X 


0 


X 


X 


X 


X 


X 


X 


X 


0 


1 


1 


1 


1 


1 


X 


X 


X 


X 


X 


X 


X 


X 


1 


X 


X 


X 


X 


X 


X 


X 


0 


1 


1 


1 


0 


1 


X 


X 


X 


X 


X 


X 


X 


0 


X 


X 


X 


X 


X 


X 


X 


X 


1 


0 


0 


0 


1 


1 


X 


X 


X 


X 


X 


X 


X 


1 


X 


X 


X 


X 


X 


X 


X 


X 


1 


0 


0 


0 


0 


1 


X 


X 


X 


X 


X 


X 


0 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


0 


0 


1 


1 


1 


X 


X 


X 


X 


X 


X 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


0 


0 


1 


0 


1 


X 


X 


X 


X 


X 


0 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


0 


1 


0 


1 


1 


X 


X 


X 


X 


X 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


0 


1 


0 


0 


1 


X 


X 


X 


X 


0 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


0 


1 


1 


1 


1 


X 


X 


X 


X 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


0 


1 


1 


0 


1 


X 


X 


X 


0 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


1 


0 


0 


1 


1 


X 


X 


X 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


1 


0 


0 


0 


1 


X 


X 


0 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


1 


0 


1 


1 


1 


X 


X 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


1 


0 


1 


0 


1 


X 


0 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


1 


1 


0 


1 


1 


X 


1 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


1 


1 


0 


0 



257 



E 


lj 14 1 j IZ 1 1 1U V 




/ 






4 




Z 


1 




At 


A? 


A, 


An 


Y 


1 


0 X X X X X X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


1 


1 


1 


1 


1 


1 X X X X X X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 


1 


1 


1 


0 









@ 








(1) 


-► 


D7 




Vcc 


«- 


(24) 


(2) 




D6 




D8 


<- 


(23) 


(3) 


-> 


D5 




D9 


«- 


(22) 


(4) 


-► 


D4 




D10 


*■ 


(21) 


(5) 


+ 


D3 




D11 


4- 


(20) 


(6) 


-» 


D2 




D12 


*■ 


(19) 






i74150 








(7) 


-► 


D1 




D13 


<- 


(18) 


(8) 


■* 


DO 




D14 


~+- 


(17) 


(9) 




E 




D15 


~+- 


(16) 


(10) 


<- 


Y 




AO 


4- 


(15) 


(11) 


-► 


A3 




A1 


*- 


(14) 


(12) 


-► 


GND 




A2 


*- 


(13) 




258 



A> 7^ 



A3 



A3 



D0>- 



D1 > 



D2>- 



D3>- 



D4>- 



D5>- 



D6> 



D7>- 



D8>- 



D9>- 



D10>- 



D11 > 



D12>- 



D13>- 



D14>- 



D15>- 



A2 



A2 



A1 



A1 



AO 



> 
> 



3> > Y 



> 



A 
E 



259 



74150 Verilog code. 



module h74150 (_Y, D, A, E) ; 
input [15:0] D; 
input [3:0] A; 
input E; 
output _Y; 
// 

function f74150 (input [15:0] D, input [3:0] A, input E) ; 
if (E == 1) 
begin 

case (A) 



0 : 


i — ■ — j n -i 1 — r\ 

f 74150 




~D 




1 : 


f 74150 




~D 


;i] 


2 : 


f74150 




~D 


:2] 


3 : 


f74150 




~D 


:3] 


4 : 


f74150 




~D 


:4] 


5 : 


f74150 




~D 


:5] 


6 : 


f74150 




~D 


:6] 


7 : 


f74150 




~D 


:i] 


8 : 


f74150 




~D 


:8] 


9 : 


f74150 




~D 


:9] 


10 : 


f74150 




~D 


;io 


11 : 


f74150 




~D 


;n 


12 : 


f74150 




~D 


;i2 


13 : 


f74150 




~D 


;i3 


14 : 


f74150 




~D 


;i4 


15 : 


f74150 




~D 


"15 



endcase 
end 
else 
begin 

f 74 150 = 1; 
end 
endf unction 



260 



// 

assign #8 _Y = f74150 (D, A, E) ; 
endmodule 



261 



74151 l-of-8 data selector or multiplexer 



74151 truth table. 



h 






Us 






v 2 


I\ 

Lt\ 




A 

A 2 




A 

A 0 


Y 


Y 


0 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


X 


1 

1 


0 


1 


X 


X 


X 


X 


X 


X 


X 


0 


0 


0 


0 


1 

1 


0 


1 


A 


X 


X 


X 


X 


X 


X 


1 


0 


0 


0 


0 


1 


1 


A 


X 


X 


X 


X 


X 


0 


X 


0 


0 


1 

1 


1 

1 


0 


1 


X 


X 


X 


X 


X 


X 


1 


X 


0 


0 


1 


0 


l 


1 


X 


X 


X 


X 


X 


0 


X 


X 


0 


1 


0 


1 


0 


1 


X 


X 


X 


X 


X 


1 


X 


X 


0 


1 


0 


0 


1 


1 


X 


X 


X 


X 


0 


X 


X 


X 


0 


1 


1 


1 


0 


1 


X 


X 


X 


X 


1 


X 


X 


X 


0 


1 

1 


1 

1 


0 


1 


1 


X 


X 


X 


0 


X 


X 


X 


X 


1 


0 


0 


1 


0 


1 


X 


v 

X 


v 

X 


1 


X 


v 

X 


X 


X 


1 


0 


0 


0 


1 




v 
A 


v 
A 


U 


v 
A 


v 
A 


v 
A 


v 
A 


v 
A 




U 


i 
1 


i 
1 


u 




X 


X 


1 


X 


X 


X 


X 


X 




0 


1 


0 


1 




X 


0 


X 


X 


X 


X 


X 


X 




1 


0 


1 


0 




X 


1 


X 


X 


X 


X 


X 


X 




1 


0 


0 


1 




0 


X 


X 


X 


X 


X 


X 


X 




1 


1 


1 


0 




1 


X 


X 


X 


X 


X 


X 


X 




1 


1 


0 


1 



(1) 


-¥ 


@ 

D3 


Vcc 


<- 


(16) 


D0> 


(2) 


-* 


D2 


D4 


<- 


(15) 


D1>" 


(3) 


-¥ 


D1 


D5 


4- 


(14) 


D2> 


(4) 












D3> 


-¥ 


DO 


D6 


<- 


(13) 








i74151 






D4> 


(5) 


4- 


Y 


D7 


<- 


(12) 


D5> 












(6) 


4- 


Y 


AO 


<- 


(11) 




(7) 










(10) 


D6> 


-* 


E 


A1 


<- 


(8) 










0) 


D7>" 


■+ 


GND 


A2 


4- 




o — •■ 



> 



262 



A> 7^ 



D0>- 



D1>- 



D2>- 



D3>- 



D4>- 



D5>- 



D6>- 



D7>- 



A2 



A2 



A1 



A1 



AO 



AO 



A 
E 



> 



> Y 



74151 Verilog code. 



module h74151 (Y, 


_Y, D, 


A, E); 


input [7:0] D; 






input [2:0] A; 






input E; 






output Y, _Y; 






// 






function f74151 


( input 


[7:0] D, input [2:0] A, input E) ; 


if (E == 1) 






begin 






case (A) 







263 



0 : 


f 7 4 1 5 1 


= D 


[0] 


1 : 


f 7 4 1 5 1 


= D 


r i i 

[ l ] 


2 : 


f 7 4 1 5 1 


= D 


[2] 


3 : 


f 7 4 1 5 1 


= D 


[3] 


4 : 


f 7 4 1 5 1 


= D 


r /i i 

[4] 


5 : 


f 74151 


= D 


[5] 


6: 


f 74151 


= D 


[6] 


7 : 


f 74151 


= D 


[7] 



endcase 
end 
else 
begin 

f 74 151 = 0; 
end 
endf unction 
// 

assign #8 Y = f74151 (D, A, E) ; 
assign #8 _Y = ~Y; 
endmodule 



264 



74153 dual l-of-4 data selector or multiplexer 



half 74153 truth table. 



E 




lJl 


I\ 

Lf\ 


Dq 




A-o 


17 

i 


1 


X 


X 


X 


X 


X 


X 


0 


0 


X 


X 


X 


0 


0 


0 


0 


0 


X 


X 


X 


1 


0 


0 


1 


U 


A 


A 


u 


A 


U 


1 

1 


U 


0 


X 


X 


1 


X 


0 


1 


1 


0 


X 


0 


X 


X 


1 


0 


0 


0 


X 


1 


X 


X 


1 


0 


1 


0 


0 


X 


X 


X 


1 


1 


0 


0 


1 


X 


X 


X 


1 


1 


1 



(1) 






@ 








-* 


Ea 


Vcc 


4- 


(16) 


(2) 


-► 


S1 




Eb 


«- 


(15) 


(3) 


■+ 


Da3 




SO 


<- 


(14) 


(4) 




Da2 




Db3 


«- 


(13) 


(5) 






i74153 








-* 


Da1 




Db2 




(12) 


(6) 


-+ 


DaO 




Db1 




(11) 


(7) 


*■ 


Ya 




DbO 




(10) 


(8) 


-* 


GND 




Yb 




(9) 



DaO>- 
Da1 >- 
Da2>- 
Da3>" 



A>- 



DbO>- 
Dbl >- 
Db2>- 
Db3>- 



2 



Ea 

V 



Eb 



> Ya 



Yb 



D0>" 
D1>" 
D2>" 
D3>" 



2 



2 y 



/2 
4 



E 

V 



/ 2 



o- 



/ 2 



A 
A1 



TOP VIEW 



265 



Ea > 
DaO> 

Da1 > 

Da2> 

Da3>- 

Eb >- 
DbO>- 

Db1 >- 

Db2>- 

Db3>- 



A> — 7 





S1 


1 




0 





so 



> 



3 



"1 



> 



> 



> 



74153 Verilog code. 



-e> Ya 



^ Yb 



module h74153 (Ya, Yb, Da, Db, A, 


_Ea, 


_Eb) ; 


input [3:0] Da, Db; 






input [1:0] A; 






input _Ea, _Eb; 






output Ya, Yb; 






// 






function f74153 (input [3:0] D, 


input 


[1:0] A, input _E) ; 


if (_E == 0) 






begin 






case (A) 






0 : f 74153 = D [0] ; 






1 : f 74153 = D [1] ; 







266 



2 • f74153 = D T 2 1 ; 






3 • f74153 = D T 3 1 ; 






p n ci c ^ s p 






end 






s 1 S G 






hpa i n 






f 741 S3 - n • 






end 






endfunction 






// 






assign #8 Ya = f74153 (Da, 


A, 

f 


Ea) ; 


assign #8 Yb = f74153 (Db, 


A, 


_Eb) ; 


endmodule 







267 



74157 quad l-of-2 data selector or multiplexer 
74157 truth table. 



E 


Da n 


Db n 


A 


F n 


1 


X 


X 


X 


0 


0 


X 


0 


0 


0 


0 


X 


1 


0 


1 


0 


0 


X 


1 


0 


0 


1 


X 


1 


1 



(1) 




A 


@ 


Vcc 


*■ 


(16) 


(2) 


-► 


DaO 




E 


4- 


(15) 


(3) 


-+ 


DbO 




Da3 


4- 


(14) 


(4) 


*- 


YO 




Db3 


+■ 


(13) 


(5) 


-+ 


Da1 


i741 57 


Y3 


-+ 


(12) 


(6) 




Db1 




Da2 


4- 


(11) 


(7) 




Y1 




Db2 


4- 


(10) 


(8) 


-► 


GND 




Y2 


-+ 


(9) 



Da> 
Db> 



4 
4 



TOP VIEW 




268 



Da>^ 



Db>^ 



A>- 



2_ 
3 



0_ 

j_ 
2_ 
3 



74157 Verilog code. 



• — (i 



> 
> 
> 

> 
> 
> 
> 
> 



^ Y 



€> 



rO 



A 
E 



module h74157 


(Y, 


Da, Db, A, _E) ; 






input [3:0] 


Da, 


Db; 






input A; 










input _E; 










output [3:0] 


Y; 








// 










function [3: 


0] 


f74157 (input [3 


:0] Da, 


input [3:0] Db, 






input A, 


input 


_E) ; 


if (_E == 


0) 








begin 











269 



case (A) 

0: f74157 = Da; 
1: f74157 = Db; 
endcase 
end 
else 
begin 

f74157 = 0; 
end 
endf unction 
// 

assign #8 Y = f74157 (Da, Db, A, _E) ; 
endmodule 



270 



Special circuits 

74148 8-to-3 priority encoder 

The 74148 is a priority encoder with negated inputs and outputs. It has an enable 
input and an enable output, used to activate the encoder and to allow concatenation 
with other 74148 modules. The output selects the higher input index and the module 
concatenation starts from the higher input module, as the last picture shows. The 
output GS (group select) is asserted if at least an input D n is asserted. 

74148 truth table. 



« 



« 



Ei 


D, 


D 6 


D 5 


D A 


D 3 


D 2 


£>i 


Do 


GS 


Eo 


Y 2 


Y\ 


F 0 


1 


X 


X 


X 


X 


X 


X 


X 


X 


1 


1 


1 


1 


1 


0 


1 


1 


1 


1 


1 


1 


1 


1 


1 


0 


1 


1 


1 


0 


0 


X 


X 


X 


X 


X 


X 


X 


0 




0 


0 


0 


0 


1 


0 


X 


X 


X 


X 


X 


X 


0 




0 


0 


1 


0 


1 


1 


0 


X 


X 


X 


X 


X 


0 




0 


1 


0 


0 


1 


1 


1 


0 


X 


X 


X 


X 


0 




0 


1 


1 


0 


1 


1 


1 


1 


0 


X 


X 


X 


0 




1 


0 


0 


0 


1 


1 


1 


1 


1 


0 


X 


X 


0 




1 


0 


1 


0 


1 


1 


1 


1 


1 


1 


0 


X 


0 




1 


1 


0 


0 


1 


1 


1 


1 


1 


1 


1 


0 


0 




1 


1 


1 



(1) 




D4 


@ 


Vcc 




(16) 


(2) 




D5 




Eo 


-* 


(15) 


(3) 


-* 


D6 




GS 


-* 


(14) 


(4) 


-* 


D7 




D3 


+■ 


(13) 








i74148 








(5) 


-» 


Ei 




D2 


4- 


(12) 


(6) 


<- 


Y2 




D1 


4- 


(11) 


(7) 




Y1 




DO 


4- 


(10) 


(8) 


-► 


GND 




YO 


-*■ 


(9) 



DO > 

D1 > 

D2 > 

D3 > 

D4 > 

D5 > 

D6 > 

D7 > 



Eo 

A 







Eo 






Y 


D w741 48 






GS 


Ei 





3 



A 
Ei 



GS 



-5* YO 

> Y1 

> Y2 



TOP VIEW 



271 



D >- 



"0 DO 



D1 



0- 



D1 



D2 |\ D2 



d2 



D3 [\ D3 



D4 |\ D4 



d4 



D5 



d5 



D6 



D7 l\ D7 



d6 



Ei >- 



Ei 



74148 Verilog code. 



o- 



o- 



Y1 



Y2 



> Eo 



> GS 



Y 



module h74148 (_GS, _Eo, _Y, _Ei, _D) ; 
input _Ei; 
input [7:0] _D; 
output _GS, _Eo; 
output [2:0] _Y; 
// 

function [2:0] f74148y (input _Ei, input [7:0] _D) ; 
if (_Ei == 0) 
begin 

if (~_D & 8'bl0000000) 

f74148y = 3'b000; 
else if (~_D & 8'b01000000) 

f74148y = 3'b001; 



272 



else if ( ~ 

V — _1 — LJ V — , — 1— _J — \ 


D & 8'b00100000) 






f74148y = 


3'b010; 






else if ( ~ 

V — _1_ LJ V — , — 1— _J — \ 


D & 8'b00010000) 






f74148y = 


3'b011; 






else if ( ~ 


D & 8'b00001000) 






f74148y = 


3'bl00; 






else if ( ~ 


D & 8'b00000100) 






f74148y = 


3 ' b 1 0 1 ; 






else if ( ~ 


D & 8'b00000010) 






f74148y = 


3'bllO; 






plop -if ( ~ 


D & 8'b00000001) 






f74148y = 


3'blll; 






else 








f74148y = 


3'blll • 






end 








else 








f74148y = 3'blll; 






endf unction 








function f74148gs 


(input _Ei, input 


[7:01 


D) ; 


if (_Ei == 1) 








f74148gs = 1; 








else if (_D == 


8'bllllllll) 






f74148gs = 1; 








else 








f74148gs = 0; 








endf unction 








function f74148eo 


(input _Ei, input 


r 7 • o l 


D) ; 


if (_Ei == 1) 








f74148eo = 1; 








else if (_Ei == 


0 && _D == 8'bllllllll) 




f74148eo = 0; 








else 








f74148eo = 1; 








endf unction 









273 



// 










assign #8 


_Y = 


f 74148y 


( Ei, 


D) ; 


assign #8 


_GS = 


f 74148gs 


( Ei , 


D ) ; 


assign #8 


_Eo = 


f 74148eo 


(_Ei, 


_D) ; 


endmodule 











A chain of two 74148. 



D >" 



16 



Eo 

A 



7 







Eo 






Y 


D w741 48 






GS 


B 





> 



2:0 



Y 




^ GS 



274 



Arithmetic units 



« 



7483 4-bit binary full-adder 

The 7483 is a 4-bit binary full-adder with carry-lookahead. The input carry is labeled 
Co, whereas the output carry is C 4 . 

7483 truth table. 



« 



A 3 


A 2 


A, 


Ao 


#3 


B 2 




Bo 


Co 


c 4 


5 3 


s 2 


Si 


So 


0 


0 


0 


0 


0 


0 


0 


0 


0 


0 


0 


0 


0 


0 


o 


o 


o 


o 


o 


o 


o 


o 


1 


o 


o 


o 


o 


1 


0 


0 


0 


0 


0 


0 


0 


1 


0 


0 


0 


0 


0 


1 


0 


0 


0 


0 


0 


0 


0 


1 


1 


0 


0 


0 


1 


0 


0 


0 


0 


0 


0 


0 


1 


0 


0 


0 


0 


0 


1 


0 


0 


0 


0 


0 


0 


0 


1 


0 


1 


0 


0 


0 


1 


1 


0 


0 


0 


0 


0 


0 




1 


0 


0 


0 


0 


1 


1 


0 


0 


0 


0 


1 


1 




1 


1 




0 


0 


0 


0 


0 


0 


0 


1 


1 


1 




1 


1 




0 


0 


0 


1 


0 


0 


1 


0 


1 


1 




1 


1 




0 


0 


1 


0 


0 


0 


1 


1 


1 


1 




1 


1 




0 


0 


1 


1 


1 


1 


0 


0 


1 


1 




1 


1 




1 


1 


0 


0 


1 


1 


0 


1 


1 


1 




1 


1 




1 


1 


0 


1 


1 


1 


1 


0 


1 


1 




1 


1 




1 


1 


1 


0 


1 


1 


1 


1 


1 


1 




1 


1 




1 


1 


1 


1 



(1) 


-► 


A3 


^ B3 


•«- 


(16) 


(2) 


«- 


S2 


S3 


■+ 


(15) 


(3) 


-+ 


A2 


C4 


-> 


(14) 


(4) 


-► 


B2 


CO 


^ 


(13) 


(5) 


-+ 


Vcc 


i7483 

GND 




(12) 


(6) 


«- 


S1 


BO 




(11) 


(7) 


■+ 


B1 


AO 


<- 


(10) 


(8) 


■+ 


A1 


so 


-> 


(9) 



C4 




CO 



TOP VIEW 



275 



4 



co>- 

0 AO 



4 



B1 



=o 



BO 



A1 



€> 
O 



A2 



B2 



A3 



B3 



o 



7483 Verilog code. 



o- 



S1 



S2 



o- 



S3 



> 



o- 



O- 



> C4 



-s* S 



module h7483 (C4, S, A, B, CO); 
input [3:0] A, B; 
input CO; 
output C4; 
output [3:0] S; 
// 

assign #12 {C4, S} = A + B + CO; 
endmodule 



276 



A chain of two 7483. 



B>" 



A> 



3:0 
7:4 



8 



3:0 
7:4 



CO 

V 



B 



~7 



CO 



w7483 s 



C4 



4 



B 



A 



CO 



w7483 S 



C4 



3:0 
7:4 



C8 



277 



« 



7485 4-bit magnitude comparator 

The 7485 is a 4-bit magnitude comparator that can be extended with other 7485 to 
increase the bit-size comparison. First are compared the inputs A and B, then, if they 
are equal, the values form ABO, BAO and EQO are used. The inputs ABO, BAO and 
EQO can be used to connect another 7485 which compares less significant digits. 



7485 truth table. 



A and B 


GTi 


EQi 


LTi 


GTo 


EQo 


LTo 


A=B 


0 


0 


0 


1 


0 


1 


A=B 


0 


0 


1 


0 


0 


1 


A=B 


0 


1 


0 


0 


1 


0 


A=B 


0 


1 


1 


0 


1 


0 


A=B 


1 


0 


0 


1 


0 


0 


A=B 


1 


0 


1 


0 


0 


0 


A=B 


1 


1 


0 


0 


1 


0 


A=B 


1 


1 


1 


0 


1 


0 


A>B 


X 


X 


X 


1 


0 


0 


A<B 


X 


X 


X 


0 


0 


1 



(1) 


-► 


B3 @ 


Vcc 




(16) 


(2) 




LTi 


A3 


* 


(15) 


(3) 


^ 


EQi 


B2 




(14) 


(4) 


-¥ 


GTi 


A2 


*- 


(13) 


(5) 




i7485 








4- 


GTo 


A1 


*- 


(12) 


(6) 


4- 


EQo 


B1 


* 


(11) 


(7) 


4- 


LTo 


AO 


*- 


(10) 


(8) 


+ 


GND 


BO 


~+- 


0) 






TOP VIEW 







A0>- 
A1 > 
A2>" 

A3>- 



V 

LTo 



V 

EQo 



A 


B 






LTi 




W7485 


EQi 






GTi 


LTo EQo 


GTo 



-<B0 
-<B1 
-<B2 
-<B3 



"<LTi 

-<EQi 
-<GTi 



278 



A>- 



4 



GTi>- 
EQi>- 
LTi>- 



B>- 



4 



-1= 



1Z 



O- 



o- 



F=8T 



> LTo 



> EQo 



F 8 ! 



GTo 



7485 Verilog code: the output ports GTo, EQo and LTo do not react exactly in 
the same way when A and B are equal and the input ports GTi, EQi and LTi 
have incoherent values. 

module h7485 (GTo, EQo, LTo, A, B, GTi, EQi, LTi); 
input [3:0] A, B; 
input GTi, EQi, LTi; 
output GTo, EQo, LTo; 
wire GT, EQ, LT; 
// 

assign #6 GT = A > B; 
assign #6 EQ = A == B; 



279 



assign #6 LT : 
// 

assign #6 GTo 

assign #6 EQo 

assign #6 LTo 
endmodule 



A < B; 

= EQ?GTi:GT; 
= EQ?EQi:EQ; 
= EQ?LTi : LT; 



A chain of two 7485. 



A 

V 



B 

V 



A 


B 






LTi 


W7485 




EQi 






GTi 


LTo EQo 


GTo 



LTo 



V V 

EQo GTo 



A 




B 






LTi 




w7485 


EQi 






GTi 


LTo 


EQo 


GTo 



< LTi 

-<EQi 
-<GTi 



280 



74181 % a' ALU 

The 74181 can work in four different modes, but not all of them have properly cal- 
culated values for the G and P ports, which should be used by a carry lookahead 
generator. Only two of the four working modes are taken into consideration in this 
chapter and for this one the ports A, B, F, G and P are "active low": in this mode 
the output ports required by a carry lookahead generator are correctly working as 
expected. 1 

The 74181 has the AeqB output port that is almost useless: it becomes active only 
when the F (or F) output is equal to lllh; on the other hand, this ALU does not 
have an output for the overflow condition. 



74181 operation table. 



S3..0 


M 


Co 


C4 F^.,0 


P 


G 


0000 


0 


0 


A 






0000 


0 


1 


A minus 1 






0000 


1 


X 


A 






0001 


0 


0 


AB 






0001 


0 


1 


(A-B) minus 1 






0001 


1 


X 


AB 






0010 


0 


0 


AB 






0010 


0 


1 


(A B minus 1 






0010 


1 


X 


A+B 






0011 


0 


0 


0000 


0 


1 


0011 


0 


1 


1111 


1 


1 


0011 


1 


0 


0000 


0 


1 


0011 


1 


1 


0000 


1 


1 


0100 


0 


0 


A plus (A+B) plus 1 






0100 


0 


1 


A plus (A-B) 






0100 


1 


X 


(A+B) 






0101 


0 


0 


A+B plus (A-B) plus 1 






0101 


0 


1 


A+B plus (A-B) 






0101 


1 


X 


B 






0110 


0 


0 


A minus B 






0110 


0 


1 


A minus B minus 1 






0110 


1 


X 


(A®B) 






0111 


0 


0 


A+B plus 1 






0111 


0 


1 


A+B 







281 



c 

•J3..0 


M 




C 17 

W F3..0 


ai 1 1 


i 
1 


v 
A 


A+Z? 


1UUU 


A 
0 


A 
0 


4 nine ( A _1_ ^ nine 1 
/I plUS \A-rLi ) plUS 1 


1 AAA 
1000 


0 


1 
1 


4 nine ±R"» 

A plUS \A +lf ) 


1 AAA 
1UUU 


A 

0 


A 


A B 


1 AA1 


A 

u 


A 

u 


A nine /? nine 1 
A piUs D piUs 1 


1001 

1 V_/V_/ 1 


o 


1 


A plus 5 


1001 


1 


x 


A ®B 


1U1U 


A 

u 


A 
\J 


(A -L/?^ nine f 4 J}\ nine 1 

^/i+i) j pius \A n ) pius i 


1U1U 


A 
U 


1 
1 


(A i nine (A T? \ 

(A +/> J plUS \A .Lt ) 


1 A 1 A 

1010 


1 
1 


A 


n 

ts 


1 A 1 1 
101 1 


0 


0 


A _I_ Tt nine 1 

a+ls pius 1 


1 A 1 1 
101 1 


0 


1 
1 


A+B 


1 A1 1 


1 

1 


v 
A 


A i I? 

A+B 


1 1 AA 

1100 


0 


0 


A plUS A plUS 1 


1 1 AA 

1 100 


0 


1 

1 


/I plUS A 


1 1 AA 
1 1UU 


1 
1 


v 
A 


1111 
1111 




A 

u 


A 
U 


4 nine (A •H\ nine 1 
/l piU5> It J piU5> 1 


1 101 


n 


1 

1 


A plus (A -5) 


1101 


1 


X 


4 -7? 


1110 


A 
W 


A 
W 


A nine I A nine 1 
A piU» \A If ) piU» 1 


1 1 1 n 


A 
U 


1 
1 


A nine ( A Tt\ 

A plUS \ A -Li ) 


1 1 1 A 


1 
1 


v 
A 


A D 

A-B 


1111 


0 


0 


A 1 1 

A plus 1 


1111 


0 


0 


A 


1111 


1 


X 


A 



282 



(1) 


■+ 


BO 


@ Vcc 


4- 


(24) 


(2) 


-> 


AO 


A1 


4- 


(23) 


(3) 


-► 


S3 


B1 


4- 


(22) 


(4) 


-¥ 


S2 


A2 


4- 


(21) 


(5) 


■+ 


S1 


B2 


4- 


(20) 


(6) 


-> 


SO 


A3 


4- 


(19) 








i74181a 






(7) 


-► 


CO 


B3 


4- 


(18) 


(8) 


-► 


M 


G4 




(17) 


(9) 


4- 


FO 


C4 


-► 


(16) 


(10) 


4- 


F1 


P4 


-► 


(15) 


(11) 


4- 


F2 


AeqB 


-► 


(14) 


(12) 


-+ 


GND 


F3 


■+ 


(13) 



A4>" 
A7>" 
A6>" 
A5>" 



C4 <^ 



G4 < 



P4 < 



4 







A B 


M 


C4 


^ w74181a 


S 


P4 


CO 


AeqB F 





V 
AeqBO 



4 

7^ 



4 

7^ 



-<B4 
"<B6 
-<B7 
-<B5 



"<M 



"<S5 
"<S7 
<S6 
-<S4 



-<co 



-=> F4 

> F5 

> F6 

> F7 



283 




284 



A 16-bit ALU with four 74181. 



C4 <- 



G4 ^r- 



P4 <- 



A 

V 



/' 4 



C4 

— w74181a s 
G4 



AeqB 



■ C4 

. _ w74181a s 
G4 



AeqB 



/' 4 



C4 

— w74181a s 
G4 



AeqB 



B 

V 



(N CO Tt O 



/' 4 



C4 M 

^ w74181a S 

^co 



-/■ <s 



-<M 



-<co 



4 x3:0 ~ 



F 



285 



A 16-bit ALU with four 74181 and the 74182 as carry lookahead generator. 



C4 < 



\ 


/ 


/ 


7 16 







A 


B 


C4 


M 




w74181a g 


G4 




P4 


CO 


AeqB F 







A 


B 


C4 


M 




w74181a g 


G4 




P4 


CO 


AeqB F 



/' 4 







A 


B 


C4 


M 




w74181a g 


G4 




P4 


CO 


AeqB F 







A 


B 


C4 


M 




w74181a g 


G4 




P4 


CO 


AeqB F 



<s 



-<M 



-v dd -p\ 



" G4 
" P4 



C3 G2 P2 



C2 G1 P1 



W74182 



■ AeqB 



286 



74181 4 b' ALU 

« 

In this mode the 74181 works using the ports A , B and F as "active high" whereas the 
ports CO and C4 are "active low", but this way the outputs G and P do not produce 
the correct value and should not be used. 2 



74181 operation table. 



S3..0 


M 


Co 


C^ 


F3..0 xp 


Xg 


0000 


0 


0 




A plus 1 




0000 


0 


1 




A 




0000 


1 


X 




A 




0001 


0 


0 




(A+B) plus 1 




0001 


0 


1 




A+B 




0001 


1 


X 




(A+B) 




0010 


0 


0 




(A+B) plus 1 




0010 


0 


1 




A+B 




0010 


1 


X 




AB 




0011 


0 


0 


0 


0000 


1 


0011 


0 


1 


1 


1111 


1 


0011 


1 


0 


0 


0000 


1 


0011 


1 


1 


1 


0000 


1 


0100 


0 


0 




A plus (A-B) plus 1 




0100 


0 


1 




A plus (A-B) 




0100 


1 


X 




(A-B) 




0101 


0 


0 




A B plus (A+B) plus 1 




0101 


0 


1 




4-7? nlus 




0101 


1 

1 


Y 








ni 1 n 


n 

u 


n 

u 








01 10 


0 


1 

1 




,4 miniiQ /? mimic 1 




0110 


1 


X 




A©fl 




0111 


0 


0 




AB 




0111 


0 


1 




A B minus 1 




0111 


1 


X 




AB 




1000 


0 


0 




A plus (A-B) plus 1 




1000 


0 


1 




A plus (A -J?) 




1000 


0 


X 




A+fl 




1001 


0 


0 




A plus B plus 1 




1001 


0 


1 




A plus B 




1001 


1 


X 




(A®B) 





287 



S3. .0 


M 


Co 


C 4 F3..0 




1010 


0 


0 


(A-B) dIus (A+ZT) dIus 1 




1010 


u 


1 

1 


<A nlns (4 + 




1010 


1 
1 


Y 


A> 




1011 


u 


u 


/I /) 




1 01 1 
1U1 1 


u 


1 
1 


/I #-« mi "fine 1 

/a 1) minus 1 




101 1 

1U 1 1 


1 

1 


Y 
/V 






1 1UU 


u 


u 


,4 T^lllQ 4 T^lllC 1 




1 1 00 

1 1UU 


u 


1 
1 


/4 nlns /4 




1 1 00 

1 1UU 


1 

1 


y 


1111 

1111 




1 101 


n 


n 
w 


A dIus (A+Z?) dIus 1 




1101 


0 


1 


A plus (A+J?) 




1101 


1 


X 


A+Z? 




1110 


0 


0 


A dIus (A +2?) dIus 1 




1110 


n 
yj 


1 

1 






1110 

1 1 1U 


1 

1 


Y 
TV 






1111 

J_ J_ J_ J_ 


0 


0 


A 




1111 


0 


0 


A minus 1 




1111 


1 


X 


A 





(1) 


■+ 


BO 


@ Vcc 


«- 


(24) 


(2) 


-» 


AO 


A1 


«- 


(23) 


(3) 




S3 


B1 


«- 


(22) 


(4) 


-» 


S2 


A2 


4- 


(21) 


(5) 




S1 


B2 


4- 


(20) 


(6) 


-» 


SO 


A3 


4- 


(19) 






i74181b 






(7) 


+ 


CO 


B3 


4- 


(18) 


(8) 


-► 


M 


xg 


-* 


(17) 


(9) 


«- 


FO 


C4 


-* 


(16) 


(10) 


<- 


F1 


Xp 


-¥ 


(15) 


(11) 


<- 


F2 


AeqB 


■+ 


(14) 


(12) 




GND 


F3 


-* 


(13) 



A4>- 
A7>" 
A6>" 
A5>" 





< 


*■ 




4- 


< 


4- 



C4 



M 



Xg 



w74181b S 



Xp 
AeqB 



CO 
F 



V 

AeqBO 



<B4 
-<B6 
-<B7 
-<B5 



-<M0 



<C0 



-<S5 
<S7 
"<S6 
-<S4 



> 



F4 
F5 

> F6 

> F7 



288 




289 



A 16-bit ALU with four 74181: the carry lookahead generator can not be used 
when input and output data are used as "active high", because the output ports G 
and P do not work properly. 



C4 < 



G4^" 
P4 <r- 



/' 4 



/' 4 



A 



B 



C4 M 
G4 w74181b S 



P4 
AeqB 

1 



CO 



/' 4 



A 



B 



C4 M 
G4 w74181b S 



P4 



CO 



/' 4 



T 





A B 


C4 


M 


G4 


w74181b S 


P4 


CO 


A 


eqB F 



4 



A 



B 



C4 M 
G4 w74181b S 

P4 CO 



-<s 



-<M 



-<C0 



3 > AeqB 



4 



15:12 



S- F 



290 



74182 carry lookahead generator 



(1) 




G1 


(a) 


Vcc 


<- 


(16) 


(2) 


> 


PI 




P2 


«- 


(15) 


(3) 


-► 


GO 




G2 


«- 


(14) 


(4) 




PO 




CO 


4- 


(13) 






i741 82 








(5) 


> 


G3 




C1 


-* 


(12) 


(6) 




P3 




C2 


-* 


(11) 


(7) 


■«- 


P4 




G4 


-» 


(10) 


(8) 


-» 


GND 




C3 




(9) 



TOP VIEW 



P3 G3 

V V 



PO GO CO 

V V V 



P1 G1 

V V 



P2 G2 

V V 



291 



A 16-bit ALU with 74182 and other ICs. 



C16 < 



-v dd 



A 

v 



OVR16 ^—^ 



A 


B 


C4 S 
W74382 


OVR 








Vdd 





G4 S ■ 

W74381 



G4 S : 

W74381 



co ; 



B 

V 



B 



G4 



3 



W74381 
P4 CO 



3:0 



-<s 



CO 

-< 



16 



G3 P3 



C3 G2 P2 



C2 G1 P1 



C1 GO PO 



■ G4 

■ P4 



W74182 



CO 



292 



74381 4-bit ALU 

« 

The 74381 is a 4-bit ALU that uses the 'G' and 'P' values to allow the carry propa- 
gation. If a bigger bit-size is required, this component needs the 74182 for the carry 
lookahead. 



74381 truth table. 



Function 


S2..0 


A3..0 


Z?3 0 


Co 


F 3..0 


Ga 


Pa 


clear 


000 


xxxx 


xxxx 


x 


0000 


0 


0 


B minus A 


001 


0000 


0000 


0 


1111 


1 


0 


B minus A 


001 


0000 


0000 


1 


0000 


1 


0 


B minus A 


001 


0000 


1111 


0 


1110 


0 


0 


B minus A 


001 


0000 


1111 


1 


1111 


0 


0 


B minus A 


001 


1111 


0000 


0 


0000 


1 


1 


B minus A 


001 


1111 


0000 


1 


0001 


1 


1 


B minus A 


001 


1111 


1111 


0 


1111 


1 


0 


B minus A 

i/ 111111 W* L J J_ M. 


001 


1111 


1111 


1 


0000 


1 


0 


A minus B 


010 


0000 


0000 


0 


1111 


1 


0 


A minus B 


010 


0000 


0000 


1 


0000 


1 


0 


A minus B 


010 


0000 


1111 


0 


0000 


1 


1 


A minus B 


010 


0000 


1111 


1 


0001 


1 


1 


A minus B 


010 


1111 


0000 


0 


1110 


0 


0 


A minus B 


010 


1111 


0000 


1 


1111 


0 


0 


A minus B 


010 


1111 


1111 


0 


1111 


1 


0 


A minus B 


010 


1111 


1111 


1 


0000 


1 


0 


A plus B 


011 


0000 


0000 


0 


0000 


0 


0 


A plus B 


011 


0000 


0000 


1 


0001 


1 


1 


A plus B 


011 


0000 


1111 


0 


1111 


1 


0 


A plus B 


011 


0000 


1111 


1 


0000 


1 


0 


A plus B 


011 


1111 


0000 


0 


1111 


1 


0 


A plus B 


011 


1111 


0000 


1 


0000 


1 


0 


A plus B 


011 


1111 


1111 


0 


1110 


0 


0 


A plus B 


011 


1111 


1111 


1 


1111 


0 


0 


A ® B 


100 


0000 


0000 


X 


0000 


0 


0 


A ® B 


100 


0000 


1111 


X 


1111 


1 


1 


A® B 


100 


1111 


0000 


X 


1111 


1 


0 


A® B 


100 


1111 


1111 


X 


0000 


0 


0 


A+B 


101 


0000 


0000 


X 


0000 


0 


0 


A+B 


101 


0000 


1111 


X 


1111 


1 


1 


A+B 


101 


1111 


0000 


X 


1111 


1 


1 



293 



Hi i n r*li rwi 

r uiidiuii 


c 


3..0 


B3..0 


^ 0 


F3..0 




p 

M 


A < If 


1U1 


1111 
1111 


1111 
1111 


Y 
y\ 


1111 
1111 


1 

1 


U 


4 . ft 
r\ • It 


1 1 0 


noon 


0000 
uuuu 


Y 
y\ 


0000 

uuuu 


u 


n 
u 


A . Z? 


1 1 0 


noon 

uuuu 


1111 
1111 


Y 

/V 


0000 


1 

1 


1 
1 


4 . /? 

/i. D 


1 1 0 


1111 

1111 


0000 


Y 

/V 


0000 


u 


n 

u 


A . ft 


1 1 0 


1111 

1111 


1111 

1111 


Y 

yv 




1 

1 


u 


Dreset 


1 1 1 

111 


noon 
uuuu 


noon 
uuuu 


Y 
/V 




1 

1 


1 

1 


preset 


1 1 1 

111 


0000 


1111 

1111 


Y 


1111 


1 

1 


1 

1 


preset 


111 


1111 


0000 


X 




1 


1 


preset 


111 


1111 


1111 


X 




1 


0 



(1) 




A1 


@ 


Vcc 


4- 


(20) 


(2) 




B1 




A2 


*- 


(19) 


(3) 




AO 




B2 


* 


(18) 


(4) 




BO 




A3 


*- 


(17) 


(5) 




SO 


i74381 


B3 


*- 


(16) 


(6) 




SI 




CO 


+■ 


(15) 


(7) 




S2 




P 




(14) 


(8) 


• 


FO 




G 


* 


(13) 


(9) 


• 


F1 




F3 


* 


(12) 


(10) 


-» 


GND 




F2 




(11) 



TOP VIEW 



A0> 
A1 > 

A2>- 
A3>- 



G4 



P4 



FO < 
F1 < 
F2 < 
F3 < 



4 








/ 


'a 




\ 




A B 


G4 








W74381 


CO 


P4 






F 





4 



<B0 
<B1 
<B2 
<B3 



<S0 
<S1 
<S2 



<C0 



294 



co> 

:--G- 




295 



A 16-bit ALU with 74381 and other ICs. 



C16 < 



-v dd 



A 

v 



OVR16 ^—^ 



A 


B 


C4 S 
W74382 


OVR 








Vdd 





G4 S ■ 

W74381 



G4 S : 

W74381 



co ; 



B 

V 



B 



G4 



3 



W74381 
P4 CO 



3:0 



-<s 



CO 

-< 



16 



G3 P3 



C3 G2 P2 



C2 G1 P1 



C1 GO PO 



■ G4 

■ P4 



W74182 



CO 



296 



74382 4-bit ALU 



74382 truth table. 



Function 


J2..0 


A3..0 


-O3..0 


^0 


^ 3..0 


OVR 




clear 


000 


xxxx 


"\/" "\/" -\r -\r 

XXXX 


X 


AAAA 

0000 


1 


1 


B minus A 


001 


AAAA 

0000 


AAAA 

0000 


0 


1111 

1111 


0 


0 


B minus A 


001 


AAAA 

0000 


AAAA 

0000 


1 

1 


AAAA 

0000 


1 

1 


0 


B minus A 


aa 1 

001 


AAAA 

0000 


1111 

1111 


0 


1 1 1 A 

1 1 10 


0 


1 


~n a 

B minus A 


aa 1 

001 


AAAA 

0000 


1111 

1111 


1 

1 


1111 

1111 


0 


1 


~n a 

B minus A 


AA 1 

001 


1111 

1111 


AAAA 

0000 


0 


AAAA 

0000 


0 


0 


n a 

B minus A 


AA 1 

001 


1111 

1111 


AAAA 

0000 


1 

1 


AAA 1 

0001 


0 


0 


Fl A 

B minus A 


AA 1 

001 


1111 

1111 


1111 

1111 


0 


1111 

1111 


0 


0 


~n a 

B minus A 


AA 1 

001 


1111 

1111 


1111 

1111 


1 

1 


AAAA 

0000 


0 


1 

1 


a r> 

A minus B 


A 1 A 

010 


AAAA 

0000 


AAAA 

0000 


0 


1111 

1111 


0 


0 


a r> 

A minus B 


A 1 A 

010 


AAAA 

0000 


AAAA 

0000 


1 

1 


AAAA 

0000 


0 


0 


a n 

A minus B 


A 1 A 

010 


AAAA 

0000 


1111 

1111 


0 


AAAA 

0000 


0 


0 


A T» 

A minus B 


A 1 A 

010 


AAAA 

0000 


1111 

1111 


1 


AAA 1 

0001 


0 


0 


A n 

A minus B 


A 1 A 

010 


1111 

1111 


AAAA 

0000 


0 


1 1 1 A 

1110 


0 


l 


A n 

A minus B 


A 1 A 

010 


1111 

1111 


AAAA 

0000 


1 


1111 

1111 


0 


1 


A T» 

A minus B 


A 1 A 

010 


1111 

1111 


1111 

1111 


0 


1111 

1111 


0 


0 


a r> 

A minus B 


A 1 A 

010 


1111 

1111 


1111 

1111 


1 

1 


AAAA 

0000 


0 


1 


A plus B 


A 1 1 

Oil 


AAAA 

0000 


AAAA 

0000 


0 


AAAA 

0000 


0 


0 


A plUS D 


A 1 1 

Oil 


AAAA 

0000 


AAAA 

0000 


1 

1 


AAA 1 

0001 


0 


0 


A plus B 


A 1 1 

011 


AAAA 

0000 


1111 

1111 


0 


1111 

1111 


0 


0 


A plUS if 


A 1 1 

011 


AAAA 

0000 


1111 

1111 


1 

1 


AAAA 

0000 


0 


1 

1 


/* » -\ Inn m_3 

A plUS D 


A 1 1 

Oil 


1111 

1111 


AAAA 

0000 


0 


1111 

1111 


0 


0 


/* » -\ Inn m_3 

A plUS Z> 


A 1 1 

Oil 


1111 

1111 


AAAA 

0000 


1 

1 


AAAA 

0000 


0 


1 


f\ Inn JL^ 

A plUS z> 


A 1 1 

Oil 


1111 

1111 


1111 

1111 


0 


1 1 1 A 

1 1 10 


0 


1 


A plus 5 


A 1 1 

Oil 


1111 

1111 


1111 

1111 


1 


1111 

1111 


0 


l 


A © B 


1 AA 

100 


AAAA 

0000 


AAAA 

0000 


X 


AAAA 

0000 


0 


0 


A © 5 


100 


AAAA 

0000 


1111 

1111 


X 


1111 

1111 


0 


0 


A © B 


1 AA 

100 


1111 

1111 


AAAA 

0000 


0 


1111 

1111 


0 


0 


A © B 


1 AA 

100 


1111 

1111 


AAAA 

0000 


1 


1111 

1111 


1 


1 


A © 5 


100 


1111 

1111 


1111 

1111 


X 


AAAA 

0000 


1 


1 


A + tS 


1U1 


AAAA 

uuuu 


AAAA 

uuuu 


v 
A 


AAAA 

uuuu 


u 


u 


A+B 


101 


0000 


1111 


X 


1111 


0 


0 


A+B 


101 


1111 


0000 


X 


1111 


0 


0 


A+B 


101 


1111 


1111 


0 


1111 


0 


0 


A+B 


101 


1111 


1111 


1 


1111 


1 


1 


A B 


110 


0000 


0000 


X 


0000 


1 


1 



297 



Function 


K ' Z..U 


At, n 


MM 1 C\ 


Co 


r i a 
-* J..U 


s\ \ / it 


Ca 


A . ft 

r\ • It 


1 1 n 


nnnn 
uuuu 


1111 
1111 


Y 


nnnn 
uuuu 


u 


u 


A ft 
/A • It 


1 1 n 


1111 

1111 


nnnn 
uuuu 


V 
A. 


nnnn 
uuuu 


1 

1 


1 

1 


A . ft 


1 1 n 


1111 

1111 


1111 

1111 


n 
u 




u 


u 


A ■ ft 

rA It 


1 1 0 


1111 

1111 


1111 

1111 


1 

i 




1 

i 


1 
i 


Dreset 


1 1 1 

ill 


nnnn 

uuuu 


nnnn 

uuuu 


Y 

y\ 




n 
u 


n 
u 


Dreset 


1 1 1 

111 


nnnn 
uuuu 


1111 

1111 


Y 




u 


u 


preset 


1 1 1 

111 


1111 

1111 


nnnn 


Y 


1111 


n 


n 


preset 


111 


1111 


1111 


0 




0 


0 


preset 


111 


1111 


1111 


1 




l 


1 



(1) 


■+ 


A1 


@ 

Vcc 


«- 


(20) 


(2) 


-* 


B1 


A2 


«- 


(19) 


(3) 


* 


AO 


B2 


4- 


(18) 


(4) 


-» 


BO 


A3 


« 


(17) 


(5) 
(6) 


-* 


SO 
S1 


B3 

i74382 

CO 


4- 

4^ 


(16) 
(15) 


(7) 




S2 


C4 


-» 


(14) 


(8) 


*- 


F0 


OVR 


» 


(13) 


0) 




F1 


F3 


» 


(12) 


(10) 




GND 


F2 




(11) 






TOP VIEW 







A0>- 
A1> 
A2>" 
A3>" 



C4 



OVR 



F0 " 

F1 < 

F2 < 

F3 <r 



4 



<B0 
<B1 
-<B2 
-<B3 



A B 


3 


0 
1 


C4 S 


«- / 




2 


W74382 








OVR CO 








F 















<so 

-<S1 
-<S2 



<C0 



298 



co> 

:""""0' 




299 



A 16-bit ALU with four 74382. 



C16 <- 



OVR16 < 



A 

v 



C4 S 

W74382 



OVR 



co ■ 



C4 S 
W74382 



OVR 



CO 



r 



7^r 



C4 S 

W74382 



OVR 



CO 



B 

V 



C4 S 
W74382 



OVR 



CO 



/ 


'16 


\ 


1 



-<s 



-<co 



1 The input port B might be used as "active high" and the operation table should be 
modified reversing all the B values: the G and P output would work correctly. 

2 The input port B might be used as "active low" and the operation table should be 
modified reversing all the B values, but the G and P output would not work either. 



300 



References 



• Wikipedia, George Boole, http://en.wikipedia.org/wiki/George_Boole 

• Wikipedia, Augustus De Morgan, http://en.wikipedia.org/wiki/Augustus_De_ 
Morgan 

• Wikipedia, Maurice Karnaugh, http://en.wikipedia.org/wiki/Maurice_Karnaugh 

• Albert Paul Malvino, Jerard A. Brown, Digital Computer Electronics, 
Glencoe/Mcgraw-Hill http://www.amazon.it/Digital-Computer-Electronics- 
Albert-Malvino/dp/0028005945 

• Stephen Brown, Zvonko Vranesic, Fundamentals of Digital Logic with Ver- 
ilog Design, Mcgraw-Hill http://www.amazon.com/Fundamentals-Mcgraw-Hill- 
Electrical-Computer-Engineering/dp/007 2823 151 ; Flip-Flops, Registers, Coun- 
ters, and a Simple Processor, http://highered.mcgraw-hill.com/sites/dl/free/ 
0072823 1 51/56549/vra23 1 51_ch07.pdf 

• Olivier Carton, Circuits et architecture des ordinateurs, http://www.liafa.jussieu. 
fr/~carton/Enseignement/ Architecture/ archi.pdf 

• Mark Gordon Arnold, Verilog Digital Computer Design: Algorithms to Hard- 
ware, Prentice Hall PTR http://www.amazon.com/Verilog-Digital-Computer- 
Design- Algorithms/ dp/0136392539 ; Verilog hardware description language, 
h ttp://www.pearsonhighered. com/samplechapter/01 3 6392539.pdf 

• IEEE, IEEE standard verilog hardware description language, http://www. google. 
com/search?q=IEEE-t-standard-t-verilog+hardware-t-description-t-language 



301 



302 



Part ii 

Simple CPU 



A simple 8-bit CPU: version "A" 307 

8.1 Version "Al": fetch and execution 309 

8.2 Version "A2": memory index 337 

8.3 Version "A3": general purpose registers 348 

8.4 Version "A4": ALU 353 

8.5 Version "A5": flags 384 

8.6 Version "A6": branching 399 

8.7 Version "A7": stack 410 

8.8 Version "A8": I/O 427 

Version "B": optimization 445 

9.1 Uniform registers 446 

9.2 Module "RAM" 449 

9.3 Module "SEL" 453 

9.4 Module "ALU" 453 

9.5 Module "TTY": the terminal 454 

9.6 Module "CTRL": control unit 459 

9.7 Memories, fields, arguments and opcodes 463 

9.8 Microcode 479 

9.9 Macrocode: routine call 496 

9.10 Macrocode: keyboard input and screen output 497 

9.11 Version "B2" 498 

Version "C": 16-bit little-endian 503 

10.1 General purpose 16-bit registers 505 

10.2 Module "BUS" 508 

10.3 Module "ALU" 509 



303 



10.4 Module "SEL" 518 

10.5 Module "RAM" 519 

10.6 Module "IRQ" 521 

10.7 Module "IVT" 529 

10.8 Module "CTRL" 531 

10.9 Opcodes 534 

10.10 Microcode 558 

10.11 Interrupts management 578 

10.12 Module "RTC": real time clock 580 

10.13 Module "TTY" 581 

10.14 Module "HDD" 586 

10.15 Macrocode: terminal usage example, through interrupts 592 

11 Version "D" 595 

11.1 General purpose registers 598 

11.2 Module "VRw" 602 

11.3 Module "RAM" 605 

11.4 Module "ALU" and related submodules 608 

11.5 Module "BUS" 615 

11.6 Module "IRQ" 616 

11.7 Modules "Dw" 617 

11.8 Module "IVT" 618 

11.9 Module "RTC": real time clock 619 

11.10 Module "TTY" 621 

11.11 Module "HDD" 625 

11.12 Module "CTRL" 630 

11.13 Memory and microcode fields 636 

11.14 Opcodes 641 

11.15 Microcode 671 

11.16 Macrocode 728 



304 



12 Version "E" 731 

12.1 General purpose modules 734 

12.2 Module "MEM" 739 

12.3 General purpose registers 744 

12.4 Module "ALU" and related submodules 748 

12.5 Module "BUS" 755 

12.6 Module "IRQ" 756 

12.7 Module "IVT" 757 

12.8 Module "RTC": real time clock 758 

12.9 Module "TTY" 759 

12.10 Module "HDD" 763 

12.11 Module "CTRL" 768 

12.12 Memory and microcode fields 772 

12.13 Opcodes 776 

12.14 Microcode 806 

12.15 Macrocode 845 

13 Version "F": 32-bit registers, big-endian, privileges 847 

13.1 General purpose modules 850 

13.2 Addition modules 853 

13.3 Multiple clock lines 857 

13.4 Bus 860 

13.5 Registers: simple and with post-increment 862 

13.6 Memory segmentation 863 

13.7 Module "DA" 864 

13.8 Module "CA" 865 

13.9 Modules "M" and "RAM" 866 

13.10 Module "IR" 871 

13.11 Module "MD" 873 

13.12 Module "IRQ" 875 

305 



13.13 Module "IVT" 877 

13.14 Module "ALU" 878 

13.15 Module "FL" 887 

13.16 Module "TTY" 890 

13.17 Module "HDD" 894 

13.18 Module "CTRL" 899 

13.19 Memory and microcode fields 902 

13.20 Opcodes 904 

13.21 Data initialization 934 

13.22 Microcode 935 

13.23 Process mode and interrupts 966 

13.24 Macrocode example: 'memcpy' 967 

13.25 Macrocode example: TTY with interrupt 969 

13.26 Macrocode example: user and supervisor 972 

References 981 



306 



307 

A simple 8-bit CPU: version "A" 



8.1 Version "Al": fetch and execution 

8.2 Version "A2": memory index 

8.2.1 Loading instructions .. 

8.2.2 Storing instructions . . . 

8.3 Version "A3": general purpose registers 

8.4 Version "A4": ALU 

8.4.1 Instruction "not" 

8.4.2 Instruction "and" 

8.4.3 Instruction "or" 

8.4.4 Instruction "xor" 

8.4.5 Instruction "lshl" and "lshr" 

8.4.6 Instruction "ashl" and "ashr" 

8.4.7 Instruction "rotl" and "rotr" 

8.4.8 Instruction "add" 

8.4.9 Instruction "sub" 

8.5 Version "A5": flags 

8.5.1 Instruction "rotcl" and "rotcr" 

8.5.2 Instruction "add_carry" 

8.5.3 Instruction "sub_borrow" 

8.6 Version "A6": branching 

8.7 Version "A7": stack 

8.7.1 Instruction "push" and "pop" 

8.7.2 Instruction "call" and "return" 

8.8 Version "A8": I/O 

8.8.1 Communication with asynchronous 

8.8.2 I/O devices implementation 



308 A simple 8-bit CPU: version "A' 



8.8.3 External appearance of the synchronous interfaces 434 

8.8.4 Synchronous keyboard interface 436 

8.8.5 Synchronous display interface 437 

8.8.6 The CPU data bus with the I/O interfaces 438 

8.8.7 Instruction "out" 443 

8.8.8 Instruction "in" 444 



fetch 309 macrocode 309 microcode 309 microcode word 309 microinstruction 309 
opcode 309 operation code 309 

Here is introduced the development of a simple CPU, gradually adding components 
and functions, up to a very simple computer. Initially, it is only a CPU with 8 -bit 
registers, including those relating to addressing of the RAM memory, which is thus 
limited to a maximum of 256 bytes. 



Attachments 


Description 


attachments/xcpu/xcpu-al . v 


TKGate Verilog netlist source file for the 
CPU version "Al". 


attachments/xcpu/xcpu-al .gm 


TKGate microcode and macrocode source 
file for the CPU version "Al". 


attachments/xcpu/xcpu-a2. v 


TKGate Verilog netlist source file for the 
CPU version "A2". 


attachments/xcpu/xcpu-a2.gm 


TKGate microcode and macrocode source 
file for the CPU version "A2". 


attachments/xcpu/xcpu-a3.v 


TKGate Verilog netlist source file for the 
CPU version "A3". 


attachments/xcpu/xcpu-a3.gm 


TKGate microcode and macrocode source 
file for the CPU version "A3". 


attachments/xcpu/xcpu-a4. v 


TKGate Verilog netlist source file for the 
CPU version "A4". 


attachments/xcpu/xcpu-a4-not.gm 

attachments/xcpu/xcpu-a4-and.gm 

attachments/xcpu/xcpu-a4-or.gm 

attachments/xcpu/xcpu-a4-xor.gm 

attachments/xcpu/xcpu-a4-lsh.gm 

attachments/xcpu/xcpu-a4-ash.gm 

attachments/xcpu/xcpu-a4-rot.gm 

attachments/xcpu/xcpu-a4-add.gm 

attachments/xcpu/xcpu-a4-sub.gm 


TKGate microcode and macrocode alter- 
native source files for the CPU version 
"A4". 



A simple 8-bit CPU: version "A' 



309 



/\liacnmeniS 


np^rn ration 

Ls\sO\*<l- 1L/L1W11 


attachments/xcpu/xcpu-a5. v 


TKGate Verilog netlist source file for the 
CPU version "A5". 


attachments/xcDu/xcDU-a5-rotc sm 

attachments/xcpu/xcpu-a5-addc.gm 

attachments/xcpu/xcpu-a5-subb.gm 


TT^f^^itp m i c rn rnnp 'A n n iti a c rnf r\f\ Qltpt"- 
1 XVvJ dLC 1111 d *JL/*JU.C ClllLl llldCl UCtiLIC dlLCl 

native source files for the CPU version 
"A5". 


attachments/xcpu/xcpu-a6. v 


TKGate Verilog netlist source file for the 
CPU version "A6". 


attachments/xcpu/xcpu-a6.gm 


TKGate microcode and macrocode source 
file for the CPU version "A6". 


attachments/xcpu/xcpu-a7. v 


TKGate Verilog netlist source file for the 
CPU version "A7". 


attachments/xcpu/xcpu-a7 -push-pop. gm 
attachments/xcpu/xcpu-a7-call-return.gm 


i Jvoate microcoae ana macrocoae alter- 
native source files for the CPU version 
"A7". 


attachments/xcpu/xcpu-a8. v 


TKGate Verilog netlist source file for the 
CPU version "A8". 


attachments/xcpu/xcpu-a8-kbd. vpd. tcl 


TCL/Tk script related to the keyboard 
module kbd. 


attachments/xcpu/xcpu-a8-dsp. vpd. tcl 


TCL/Tk script related to the screen mod- 
ule DSP. 


attachments/xcpu/xcpu-a8-out.gm 
attachments/xcpu/xcpu-a8-in.gm 


i Jvoaie microcoae ana macrocoae alter- 
native source files for the CPU version 
"A8". 



8.1 Version 7\1 ": fetch and execution 

« 

In its first attempt, the CPU consists only of registers useful to access the memory, to 
read the opcode that should be executed, as shown in the next figure. 



310 



A simple 8-bit CPU: version "A' 



Figure 8.2. Simple CPU version "Al". 




The simpler module that can be analyzed is the oscillator, which produces the clock 
signal. It is an oscillator constructed with a series of inverting logic gates, to create 
a propagation delay sufficient to produce an oscillation at a manageable frequency. 
To activate the oscillation is required an initial pulse, which, after a short time to 
zero, is activated permanently. The next figure shows the oscillator and the start pulse 
necessary for activation. It is important to note that the series of inverter gates must be 
in odd number, as if it were a single inverter gate, but with a long propagation delay. 
The result is then given to a frequency divider, composed in this case of a chain of 
synchronous T flip-flops; the output is made of many lines grouped together, each of 
which allows to select an oscillation at a different frequency. The frequency divider 
is initialized by the same initial pulse, which starts from a state to zero. In the case of 
the examples is used a very low frequency, obtained from the last stage of division. 



A simple 8-bit CPU: version "A" 

Figure 8.3. Oscillator used for the clock signal. 



311 



Fdiv 



Fout 



Clr 



frequency 
divider 

Fin 



O^>H>0H>H>l>H>i 

r<r<Kr<H<<h<i 



FO 



-> 

Figure 8.4. Frequency divider used inside the oscillator module: the divider is 
made of 12 T flip-flop, but the figure shows only four of them. 

> Fout 



o a)|co|N|tD|m|-3-|co|c\i|T- o 





Preset 




Q 






T 


Q 






Clk 




Clear 





Clr >- 



Preset 



to 



-O 



cik ; 



Preset 



Clk 




-< Fin 



The initial impulse is produced by a component synthesized through the Verilog code 
because otherwise would be necessary to use analog electronic components and their 
discussion is beyond the scope of this study. 



312 



A simple 8-bit CPU: version "A' 



Figure 8.5. Verilog code for TKGate, relative to the trigger module used to start 
the oscillation: the output is initially zero, and after a brief moment it passes to 
one, thus remaining permanently. 

module one_up (Z); 
output Z; 
reg Z; 
initial 
begin 

Z = 1'bO; 

// wait 1 ms: the timescale is 1 ns 

#1000000; 

// activate the output value 

Z = l'bl; 

end 
endmodule 

The control unit, contained in the CTRL module, is very similar to that described in 
section 7.3, with the difference that the input is identified by the 8 -bit variable / (the 
letter T stands for 'instruction') and that the output has a much higher bit range, 
forcing to use two memory units in parallel. The counter that is used to scan the 
instructions in the final block of memory has a total of 16 bits, but for convenience, 
two 8 -bit counters were used in cascade. The input / of the control unit is fed by the 
IR register content (instruction register). 



A simple 8-bit CPU: version "A' 



3 



Figure 8.6. Control unit: first there is the 8-bit counter module (microprogram 
counter) based on D flip-flops; then it appears the detail of the counter, in two 
alternative implementtions. 



i 

V 



map 



0 1 



start 



cnt 



Clk 



Clr > 



L 



c 


D 


E 


Clk 


cnt 




L 


Q 


Clr 



Clk 
L 



cnt 



Clr 



> > 

^« _l- § i microcode 

= O - D 


jump to instruction execution 




0 

► 1 


/ 


« 




/ 
CO 

cn 

CO 

ro 


/ 32 

CO 

o 



L 



V 

CON 



314 



A simple 8-bit CPU: version "A' 




<E 



The modules IR, MAR and MDR, are simple registers, constructed with D flip-flops, 
connected to the bus through tri-state buffers. From these register it is possible to 
pick up a copy of the value stored by an additional output, called data . The register 
IR (instruction register), already mentioned, has the purpose to keep the opcode that 
the control unit should execute; the register MAR (memory address register) has the 
purpose to keep the memory address to which the memory is to be accessed; the 
register MDR (memory data register) is used to accumulate what is read from the 



A simple 8-bit CPU: version "A" 315 
memory for some reason or what is to be written to the memory. 

Figure 8.7. Registers IR, MAR and MDR. The diagram on the right is a compact 
version of the same circuit. 



Clr Clk 



data bw 




bus 



4- 


+ 


4- 


br 


data 


bw 


Clk 


MDR 


Clr 




bus 






i 






t 


+ 


br 


data 


bw 


Clk 


MAR 


Clr 




bus 












t 


4- 


br 


data 


bw 


Clk 


IR 


Clr 




bus 







'dd 



Q 


Preset 






D 


Q 




Clk 




Clear 





v- 



data 



-< bw 



0 

bus 



< br 



< Clk 



< Clr 



The PC module is a register similar to the others, with the difference that it may 
increase the value that it contains when the input Inc is asserted. The register PC 



316 A simple 8-bit CPU: version "A" 

{program counter) is intended to contain the memory address of the next opcode to 
be executed. 

Figure 8.8. Counter register PC. The diagram on the right is a compact, equiva- 
lent circuit. 

Inc Ok 

w v 



+ t \ 




The RAM module is substantially different from the others, as it contains the RAM 



A simple 8-bit CPU: version "A' 



317 



used by the CPU. This memory is accessed through the address provided via the 8-bit 
Addr input, but also the content of the memory is organized in 8 -bit cells. The module 
shares with the others the same inputs to control the data bus access, but when the RAM 
module receives the address and the data bus read is enabled, the value in memory 
is updated immediately (except for the propagation delay), without waiting until the 
clock pulse reaches a positive edge. 

The RAM module receives the address from the MAR register, which is dedicated to 
hold the memory address to which the memory access should be done. 

Figure 8.9. Module RAM. The logic network that controls the inputs br and bw, 
prevents the simultaneous read and write of the data bus. 

br 

v 



Addr>- 



m3 



A D 



■o bus 



br Addr bw 



RAM 



bus 



A 

bw 

The first thing that the structure described above should do is to load an opcode in- 
struction, followed by the execution of it: this is known as fetch cycle. In this structure 
the PC register contains the address of the instruction to be executed: this value must 
be transferred to the MAR register and the PC register is incremented: the instruc- 
tion is obtained from the RAM at the address specified by the MAR register and it is 
copied to the IR register. This can be summarized as follows: 



1. MAR = PC 



2. PC++ 



318 



A simple 8-bit CPU: version "A' 



3. IR = RAM \ MAR | 

The following figures show just three steps, pointing out the values of br, bw and 
Inc inputs, with LEDs, which turns red when the line to which they are connected is 
activated. The figures show the time when the clock signal becomes active. 

Figure 8.10. First phase: it is requested to the PC register to send its value to 
the data bus and to the MAR register to read it. This implements in practice the 
operation MAR=PC. 



In 
u 


n 


n 
>-i 


n 
u 






16 1 10 



In 
i-i 


n] 
i_< 




n 
u 


ri\ 
i.i 




16 


| 10 




A simple 8-bit CPU: version "A' 



319 



Figure 8.11. Second phase: it is requested to the PC register to increase by one. 
This implements in practice the operation PC++. 




320 



A simple 8-bit CPU: version "A' 



Figure 8.12. Third phase: it is requested to the RAM to send the value at the 
address pointed by the MAR register to the data bus and it is requested to the IR 
register to load it. This implements in practice the operation IR=RAM[MAR]. 



I 



11 

resume 



a 



<5 



stop 



34 31 

23_43_ 
18~_G_ 
_L£_L£. 



14 13 



1? 11 



s_s_ 



br data bui 
!» CTRL clr fa rJclk IR clr 



II II II II 
l-< l-l l.l U 



JTo" 



T 



-D 



ii ii ii ii 
u u i_i U 



JTo" 



4 



br Addr bw 
RAH 

bus 



D 



br data bw 
r^clk MAR clr 
bus 



D 



n r< r< 
i.i i.i i.i 



□pep 



-D 



br data bw 
|-rr)clk MDR clr 

bus 



D 



br data bw 

Inc hF" 



bus 



ff clear 











>"l 


n 
i.i 




B 


ri 
i.i 


Ml 
>.i 


ril 
>_jj 



Within the control unit (the CTRL module) time is marked in the same way, apart from 
the fact that the counters cnt are driven by an inverted clock signal, to anticipate the 
activation of the control lines with respect to the data bus. Initially the counters of 
the control unit are cleared, so that they point to the first microinstruction, which is 
the request to perform the operation MAR=PC. Then, the microcode counter (the 
group of the two counters cnt) is incremented and the new value points to the second 
microinstruction, which is the request to increase the PC register. Then, there is a 
further counter increase, bringing to the microinstruction IR=RAM[MAR]. 



A simple 8-bit CPU: version "A' 



321 



Figure 8.13. First phase: the counters of the control unit are reset and the initial 
microinstruction is MAR=PC. 

u 





-» 






Fdiv 


T 







ON 
OFF 



TBL 



n 


:n 


n 


u 




U 


:u 


u 


< 


/ 

/ 




jump to instruction execution 



•51 . n 


"■86 




4— L- 






I 




5tT32 









< 

< 


t 



322 



A simple 8-bit CPU: version "A' 



Figure 8.14. Second phase: the set of counters has been increased and the mi- 
croinstruction produced is PC++. 

0 



ON 
OFF 



- TBL 



3> 



n 


n 


n 


u 




u 


:u 


u 








51 0 


"496 








I 


H 










< 

< 


r 



A simple 8-bit CPU: version "A' 



323 



Figure 8.15. Third phase: the set of counters has been increased and the microin- 
struction produced is IR=RAM[MAR]. 



ON 
Off 



TBL 



n 


:n 


n 


>_< 




u 


:u 


u 







16 



start 




jump to instruction execution 



35 



T 



-i-5-52 



32 
_j 



^36 



At this point, the control unit has received the opcode from the input / and is ready 
to execute it. To do this, the next microinstruction requires the microcode counter to 
accept the input value. This value is the content of the memory bank mO at the address 
represented by the opcode itself. The value obtained from the memory bank mO is 
the microcode address to be executed. In the examples of the figures, the opcode is 



324 



A simple 8-bit CPU: version "A' 



OOOOOOOO2 that is named not_operate (do nothing). 



Figure 8.16. Fourth phase: the counters of the control unit are loaded with the 
value from the memory bank that translates the opcode instruction into a mi- 
crocode address. 

0 



Fdiv 



ON 
OFF 



- TBL 



n 


:n 


n 


u 




U 


:u 


u 


< 


/ 

/ 




JT 

jump to instruction execution 





. 34*0/ 






1 4 








7^ 


< 


t 



A simple 8-bit CPU: version "A' 



325 



Figure 8.17. Final phase: the counters of the control unit have been increased and 
point to the next microinstruction. Since the original instruction (not_operate) 
did not require the performance of any operation in the data bus, the current mi- 
croinstruction requires to the microcode counter group to reset to zero. The reset 
is done by loading the counters with zero through the multiplexer that controls 
the input of these counters. 



n 
u 



Fdiv 



11 

32 



0 



i 



CNT 



TBL 



m I 



n 
U 



n 



16 



' 1 



VZ7 



start 



lis: 

4- 



15 



C E 

CJLk Cnt 

L clr 





D 




( 




E 


ClJt 


cnt 




L 


Q 


Clr 



15:^_0l_ 



JT 



jump to instruction execution 



35 :;»;.» 



' 32 







^1 


0 , 


'*<6 


II II 


— < 




1 




J : : 


2 






^^^^ 




— < 

< 





After resetting the counters of the control unit, it all starts from the initial microcode 



326 



A simple 8-bit CPU: version "A' 



(the first three phases) which requires to do load a new instruction. During the fourth 
phase (jump to the microcode execution of the requested opcode) and during the final 
phase (jump to the microcode implementing the initial fetch cycle), inside the data 
bus nothing happens. 

Figure 8.18. During the fourth phase (jump to the microcode execution of the re- 
quested opcode) and during the final phase (jump to the microcode implementing 
the initial fetch cycle), inside the data bus nothing happens. 



I 



1-1 


ri\ 
u 


In 
u 


n 
u 


n\ 
u 




16 1 10 



' j i i u 



Fdivf F0 



11 
resume 



i 



:ll CTRL clr T 



a 



15 



stop 



«■ 31 

23_43_ 
18~J2_ 
_L£_li 



U 13 
1? 11 
1» 1 

— 



-D 



a -rO 



br data bw 
r^clk IR clr 

bus 



1 1 n n n 
u u >-< '-' 



JTo" 



br Addr bw 
RAM 
bus 



br data bw 
r^r|clk MAR clr 
bus 



D 



n n n n 
u U u u 



-D 



T 



EBP 



br data bw 
r^jcik MDR clr 

bus 



-D 



D 



JTo- 



br data bw 
Inc 



f f clear 



Hnnn 



To stop the operation of the described circuit, there is the stop instruction 
(11111111 2 ), which stops the clock signal. The figure below shows this situation. 



A simple 8-bit CPU: version "A' 



327 



Figure 8.19. The data bus when the instruction stop is executed: the control line 
CON 35 is activated and blocks clock signal. To resume execution from that point, 
overcoming the stop, should turn on and off the switch located near the LED that 
is active. 





B 


m 


c 

_t 


T 
_< 


MINIM 






16 1 10 







□II 




1 "1 




I 


16 V 1 10 





n 
u 














16 


|10 




There should be available two videos that demonstrate the execution of only two 
instructions (macroinstructions) : 

1. not_operate 

2. stop 

The first video ogv http://www.youtube.com/watch?v=8MahVvyBUOo shows what 
happens in the data bus, whereas the second one shows what happens inside the con- 
trol unit ogv http://www.youtube.com/watch?v=pPxCQz7IFbM . 

To describe the content of the memory banks, including the RAM, a source file 
is used. The source file is written according to the syntax suitable for TKGate 2 
(gmac precisely). The first directives describe the memory banks, which are orga- 
nized so: ctrl .mO is the first memory bank at the top of the control unit, ctrl .ml 
and ctrl .m2 are the two memories that contain the microcode and are located at the 
bottom of the diagram of the control unit, ram.m3 is instead contained in the RAM 
module of the data bus and it contains the macrocode that initially is limited only to 



328 

not _ope rate and stop. 



A simple 8-bit CPU: version "A" 



map 


bank [7 : 0] 


Ctrl . mO ; 


microcode 


bank [31 : 0] 


Ctrl . ml ; 


microcode 


bank [35:32] 


Ctrl . m2 ; 


macrocode 


bank [7 : 0] 


ram . m3 ; 



Figure 8.21. Where are located the memory banks. 

map 




br 

v RAM 



Addr> 




o bus 



rmcrocode 



macrocode 



The source file then continues with the fields that divide each microcode word (the 
memory cell used to represent a single microinstruction, made of ctrl.ml and 
ctrl.m2 joined together). For example, the least significant bit is called ctrl_start, 
while the most significant is called stop . It should be noted that not all the 36 bit of the 
microcode word are described, because at the moment the code is limited to represent 
the reduction of the CPU in its first version. 



field 


ctrl_start [ 0 ] ; 


// start from address 0 


field 


ctrl_load [ 1 ] ; 


// load Inside the counter 


field 


pc_br [ 2 ] ; 


// PC < — bus 



A simple 8-bit CPU: version "A' 



329 



field 


dp bw r 3 1 : 


// PC — > bus 


field 


nr Tnr r 4 1 ; 

n-' \ -i— j. j. v * L J / 


// PC++ 


field 


md t h) t T 9 1 : 


// MDR < — bus 


field 


md t bw r 1 0 1 '. 

ILL V A. _L_ _k_/ VV 1 _1_ V_/ J / 


// MDR — > hus 


field 


rrir5 t br r 1 1 1 : 

ILL V^L J _K_y J 1 I _1_ I # 


/ / MAR < bus 


field 


mar bw [121; 


// MflJ? — > jbus 

mm A 46* » m*Mr 


field 


Tr3m hr T 1 3 1 : 

J Iw^L ILL _K_y J 1 _1_ ' I # 


// RAM [marl < — jbus 


field 


Tflm bw T 1 4 1 r 

_L_ l_A 1 L L _K_y VV 1 _1_ J / 


// RAM [ma. r 7 — > bus 


field 


i r _b r [ 1 5 ] ; 


// Ji? < — Jbus 


field 


i r_bw [16] ; 


// JR — > Jbus 


field 


stop [ 35 ] ; 


// stop clock 



The source file then describes the types of operands that the macroinstructions may 
have. It is expected to manage instruction operands without operands, or with only a 
single 8-bit operand. The meaning of the syntax used to describe the type op_0 and 
the type op_l should be intuitive: the former means no argument, while the latter 
means the presence of a single numeric 8-bit argument. 



operands 


op_0 { 


// 




// [■ 


] 


// 




}; 


{ }; 


operands 


op_l { 


// 




// [■ 


] [nnnnnnnn ] 


// 




#1 = 

I; 


{ +1=#1[7:0]; }; 



There are then the opcode descriptions. For example, the instruction not_operate 
is equal to the zero opcode (OOOOOOOO2), while the jump instruction has the opcode 
15 (00001 1 1 1 2 ). It should be noted that in the first case (not_operate) there are no 
arguments, while in the second one an argument is required. 



330 



A simple 8-bit CPU: version "A' 



op not_operate { 

map not_operate : 0; 
+0 [7 : 0] = 0; 






operands op_0; 

}; 






op j ump { 

map jump : 15; 
+0 [7 : 0] = 15; 


// 


jump to #nn 


operands op_l ; 

}; 






op stop { 

map stop : 2 55; 
+0 [7 : 0] =255; 


// 


stop 


operands op_0; 

}; 







Then begins the microcode definition, which is placed starting from the first mi- 
crocode word (address zero of the pair of memories ctrl . ml and ctrl . m2). It begins 
from the description of the fetch and it ends with a jump to the microcode associated 
to the loaded opcode. Then, at the end of the description of each opcode (in the form 
of microcode), it is required to jump back to the first microinstruction, which repeats 
the fetching cycle. 



begin microcode @ 0 




// 




fetch : 




mar_br pc_bw; 


// MAR = PC 


pc_Inc; 


// PC++ 


i r_b r r am_b w ; 


// IR = RAM [MAR] 


ctrl_load; 


// jump to the 




// microcode implementing 




// the loaded opcode 


not_operate : 




ctrl_start ctrl_load; 


// jump to a new fetch 


// 





A simple 8-bit CPU: version "A' 



331 



i iinrD ■ 

J \-A. ILL ' • 






ILLd J_ iU _L UL/ -kJ W f 


// MAR : 




"dp h"r r^m Idw ; 

' V ^ -k_/ _L_ _L_ ILL -k_^ V V # 


// PC <■ 


— RAM [MAR! 


ctrl start Ctrl load; 


// lumjD 

ft j v **** < £^ 


to a nev fetch 


// 






O l_ k-^ • 






s t op ; 


/ / StOlD 


clock 


// T ■f 1- /-» 7 /->/-» fc- c? i rrn a 7 t cr 

/ / XX UiiC OX UUA. dlUiial XO 






// resumed ma.nua.llv' 






ctrl start ctrl load; 


/ / lUItlO 


to a. new fetch 


// 






end 







Figure 8.26. Match between the contents of the memory that represents the mi- 
crocode (the couple of memory banks ml and m2 inside the control unit) and the 
microcode description itself. 



% 3 



£ / 

-Q : 
J 



< 5- 
CO ; <fe / 



4 



4. . O: 



-O; 



Cr/ 



hJS h.H bii bil h.M h.W h2^) H2S h27 h26 h25 h24 h23 H22 H21 H2U HI9 his h!7 hlfi MS h!4 b!3 h!2 hi 1 hlO W 



f t A / / 

W bi bS M b3 b2 bl bO 



fetch: 




























c 


0 




c 


0 


0 












1 




0 








0 




1 


































c 


c 


0 


D 


0 


c 












0 


c 


0 






0 


0 


1 




































[) 






0 


a 


c 




1 


1 


























































0 




0 


c 


































i 








perate: 






























c 




c 


c 


c 




























c 




l 


l 




jump: 




























a 


a 




a 


a 


a 












1 
















1 


































a 


a 




0 


0 


i 






1 






















a 


l 
































a 


a 




0 


0 


i 




























a 




l 


l 






stop: 


l 


























D 


0 




0 


0 


0 


c 


c 


c 


c 


c 








c 


c 










































is 


0 




0 


0 


0 
































i 


i 



Finally, it starts the macrocode, or assembler code, which should be placed inside the 
RAM memory: 



begin macrocode @ 0 
start : 

not_operate 
stop 

end 



332 



A simple 8-bit CPU: version "A' 



Figure 8.28. Macrocode contained inside the RAM memory. The memory cells 
marked with "xx" have an unspecified and unknown value. 



start: 



oo 

10 
FO 



not_operate 
^stop 



o 



6 7 8 



A B C D 



00 


FF 































































0123456789ABC 
Table 8.29. Macroinstructions list for this first version of the CPU. 



D 



OF 
IF 

FF 



Syntax 


Description 


not_operate 


Do nothing, just go to the next instruction. 


jump #ref 


Jump to the instruction that is located at the specified 
address in memory. 


stop 


Stop the clock. 



The source file described above should be available at attachments/xcpu/xcpu-al .gm . 
If follows the procedure to compile it with gmac20, the TKGate 2 code compiler: 

$ gmac2 0 -o x.mem -m x.map ^ 
^ xcpu-al . gm [Enter] 

The compilation produces the file 'x . mem' that contains the images for all the memory 
banks. It is a text file and it looks like this: 

Qmemory ctrl.ml 



@0 

808 10 cOOO 2 3 808 4004 3 
0 3 



A simple 8-bit CPU: version "A' 



333 



@memory 


Ctrl . m2 


@0 

0 0 0 0 
8 0 


0 0 0 0 


@memory 


Ctrl . mO 


@0 
4 




@f 
5 




@f f 
8 




@memory 


ram. m3 


@0 

0 ff 





The compilation produces also the file 'x.map' that contains the microcode and 
macrocode maps; that is, the addresses of known labels: 



Microcode 


Symbols 


(total 


= 4) : 




fetch 








00000000 


jump 








00000005 


not_ope 


rate 






00000004 


stop 








00000008 


Macrocode 


Symbols 


(total 


= 1) : 




Global 




Local 







334 



A simple 8-bit CPU: version "A' 



start 00000000 



The file 'x . mem', produced by the compilation, is used by TKGate 2 to load the mem- 
ory banks initial contents. But an additional script is necessary: 

module LM ( ) ; 
initial 
begin 

$readmemh ("x.mem") ; 
end 
endmodule 



This is a simple module — called LM inside the TKGate Verilog netlist source — that 
should be placed somewhere, just to make it work at the beginning of the TKGate 
simulation. The script is responsible to load the file 'x . mem' to the memory banks. 

The TKGate 2 Verilog netlist source should be available at attachments/xcpu/xcpu-al . 
v and TKGate might be used to experiment with this CPU version with the following 
command: 

$ tkgate20 xcpu-al . v [Enter] 

This first CPU version has also another instruction, not yes experimented: jump. The 
jump is done with the following steps: 

1. MAR = PC 

2. PC = RAM \ MAR | 

That is: the MAR register receives a copy of the PC register, which contains the ad- 
dress following the jump opcode. At the MAR address, the memory contains (should 
contain) another address, which is copied back to the PC register (and no increment 
is applied to the PC register). 

The jump opcode precedes an argument: a number representing a memory address, 
which is the place where the PC register should point, so that the next instruction 
would be that one located at the new address position. When the argument is read, it 
is not sent to the IR register, because it is not an opcode. 



A simple 8-bit CPU: version "A' 



335 



The following macrocode example shows an infinite loop. Please notice that the 
TKGate compiler transforms the string #start into the address matching the label 
start inside the RAM memory: as the label start appears at the first position, it 
matches to the address zero. 

begin macrocode @ 0 
start : 

not_operate 
jump # start 
stop 

end 



start: 



Figure 8.34. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

not_operate 
jump 

#start 
- stop 

3 4 5 6 



00 
10 



0 



1 



7 8 



A B 



D 



00 


OF 


00 


FF 



























































OF 
IF 



F0 



FF 



0123456789ABCDEF 
As it is an infinite loop, the stop is never reached. The following figures show what 
happens on the data bus after the instruction not_operate is executed. 



336 



A simple 8-bit CPU: version "A' 



Figure 8.35. The jump opcode is loaded and the PC register is pointing to the ad- 
dress following it; the MAR register is loading the memory content at the address 
pointed by PC. 







Fdiv 


FO 


, 1* 


V 



» L 

resume 



E 




a 



stop 




A simple 8-bit CPU: version "A' 



337 



Figure 8.36. The PC register is loaded with the value contained in memory at the 
address pointed by the MAR register. 




There should be available a video showing the example above: ogv http://www. 
youtube.com/watch?v=Z8bT08WjYYc . 



8.2 Version 7\2": memory index 

The second CPU subversion adds only a special register, named / (index), which 
should contain a memory index. It should be used to read and write the RAM memory 
through an index that could be managed. The / register is made the same way as 
MDR, MAR and IR. 



338 



A simple 8-bit CPU: version "A' 



Figure 8.37. Simple CPU version "A2". 




Inside the code that describes the microcode word fields, the following fields are 
added: they are used specifically to manage the / register: 



field 


i_br [2 9] ; 


// I 


< — bus 


field 


i_bw [30]; 


// I 


— > bus 



Inside the opcode list there are new instructions and the same is for the microcode 
description: 



op load_ref 

{ 

map load_ref : 


i; 


// load 


from 


address 


#nn 


+ 0 [7 : 0] =1; 












operands op_l; 

}; 












op load_reg 

{ 

map load_reg : 


2; 


// load 


from 


address 


%I 


+0 [7 : 0] =2; 












operands op_0; 













A simple 8-bit CPU: version "A' 



339 



}; 

op store_ref { 
map store_ref : 
+0 [7 : 0] =3; 


3; 


// 


store to address 


#nn 


operands op_l ; 

}; 










op store_reg { 
map store_reg : 
+0 [7 : 0] =4; 


4; 


// 


store to address 


I 


operands op_0; 

}; 










op move_mdr_i { 
map move_mdr_i 
+0 [7 : 0] =11; 


: 11; 


// 


move MDR to I 




operands op_0; 

}; 










op move_i_mdr { 
map move_i_mdr 
+0 [7 : 0] =12; 


: 12; 


// 


move I to MDR 




operands op_0; 

I; 











begin microcode @ 0 




load_ref : 




mar_br pc_bw; 


// MAR < — PC 


pc_Inc; 


// PC++ 


// The RAM memory does not 


have a clock, 


// thus, it is not possible 


to do just 


// MAR < — RAM [MAR ] 




i_b r r am_b w ; 


// I < — RAM [MAR ] 


mar_br i_bw; 


// MAR < — I 


mdr_br ram_bw; 


// MDR < — RAM [MAR ] 


ctrl_start ctrl_load; 


// CNT < — 0 



340 



A simple 8-bit CPU: version "A' 



// 








load reg: 








i l l o. j_ j_ _i_ vv f 




// 


MAR < J 


mdr_br ram_bw; 




// 


MDi? < — RAM [MAR] 


ft T 1 StS'Tt P1"T"1 


load; 


// 


CNT < — 0 


// 








store re f ; 








mar br pc bw; 




// 


MAR < — PC 


or I n c : 






PC++ 


i br ram bw; 






I < — RAM [MAR] 


mpi t V~)T i hw ■ 

ILL d J_ J_ _1_ LJ Vv ^ 




/ / 


MAR < I 


ram_br mdr_bw; 




// 


RAM [MAR] < — MDR 


ctrl start" otrl 


load; 


// 


CNT < — 0 


// 








store reg : 








mar V") T~ i hw ' 




// 


MAR < — I 


ram br mdr bw; 




// 


RAM [MAR] < — MDR 


ctrl start otrl 


load; 


// 


CNT < — 0 


// 








Tnn\/p rriHr i • 








i_br mdr_bw; 




// 


I < — MDR 


rt rl stsrt ft rl 


load; 


// 


CNT < — 0 


// 








move_i_mdr : 








mdr_br i_bw; 




// 


MDR < — I 


ctrl start Ctrl 


load ; 


// 


CNT < — 0 


end 









A simple 8-bit CPU: version "A' 



341 



Figure 8.41. Match between the contents of the memory that represents the mi- 
crocode (the couple of memory banks ml and m2 inside the control unit) and the 
microcode description itself. 



h.S h34 b33 Kg bM b30 W9 b28 b27 h26 H2? h24 b23 h22 H21 H2U his) MS h!7 big M5 h!4 b]3 h!2 bll blO W W t7 b6 bi M b3 b2 bl bO 



load_ref: 





a 




□ 








a 


















□ 


□ 








: 






1 


□ 








:: 


:: 




1 




□ 




c 








c 


c 


: 














C 


: 


















: 










C 






1 


c 


c 






0 








c 


: 


1 














0 


C 














1 


0 


: 
















C 


c 


c 








a 


□ 






1 




: 




























: 






1 










: 


: 














a 


□ 


□ 








: 
















:: 


□ 


□ 






□ 


1 










1 






: 


: 








a 




0 










: 


: 












D 


0 


















0 


0 
















0 






l 


l 



load_reg: 



0 










i 


































0 


0 


1 














c 




























■ 








■ 


■ 










■ 




l 


i 








l 




■ 






a 












a 












a 
















a 












a 








a 








a 










l 


l 



store_ref: 



c 


a 








c 


C 


a 












c 


c 


a 












a 




c 


1 








■ 


a 


a 


; 


1 








0 








c 


c 


: 














c 


0 










c 






0 


: 
















1 


c 


c 






0 








s: 


: 


1 














0 


c 










c 




i 


0 


C 
















C 


c 


c 










a 


a 




1 




a 
















a 


a 








a 


a 






1 


a 


















a 


a 




a 


a 


a 








a 


















a 


a 






a 


a 


i 






i 








a 


a 








a 


a 


c 












: 












D 




0 
















0 


0 
















0 






l 


l 



store_reg: 



c 










l 


































0 




l 






























:: 
























:; 












:; 


l 






l 










a 














a 


a 


a 








a 
















a 












: 








a 








a 


a 








l 


l 



move_mdr_i: 





a 








c 


1 


a 












c 


c 


a 












a 




c 




1 








a 


a 


i 










c 








c 


c 


c 






c 








c 


c 










c 






0 


: 








c 


c 






0 


c 


c 


1 


1 




0 


0 






i 


1 


I 






0 








0 


0 










0 








0 






l 


0 


0 






0 


0 


0 








:: 


a 










a 


















a 


a 
















a 








a 


a 








1 


1 



Table 8.42. Macroinstructions added for this version of the simple CPU. 



Syntax 


Description 


load_ref %ref 


Load reference: it loads the value contained in mem- 
ory, at the specified address, into the MDR register. 
The / register loads the argument. 


load_reg 


Load register: it loads inside the MDR register the 
value contained in memory, at the address pointed 
by the / register. 


store_ref #re/ 


Store reference: it copies into the memory, at the ad- 
dress specified by the argument, the value contained 
inside the MDR register. The / register loads the ar- 
gument. 



342 



A simple 8-bit CPU: version "A' 



Syntax 


Description 


store_reg 


Store register* it conies into the memorv at the ad- 
dress pointed by the / register, the value contained 
inside the MDR register. 


move_mdr_i 


It copies the MDR register into the / register. 


move_i_mdr 


It copies the / register into the MDR register. 



8.2.1 Loading instructions 

As a first example, the following macrocode is proposed: 

begin macrocode @ 0 
start : 

load_ref #data_l 

move_mdr_i 

load_reg 

stop : 

stop 

data_l : 

.byte 3 

end 



The address matching the label data_l is loaded into the MDR register (it is the 
address 5). Then, MDR is copied into / (it is the value 3). Then, the value contained 
in memory at the address pointed by / is copied to MDR. At the address 3 there is the 
instruction load_reg which has the opcode 2: that is, at the end the MDR register 
contains the value 2. The full source should he available at attachments/xcpu/xcpu- 
a2.gm . 



A simple 8-bit CPU: version "A" 



343 



Figure 8.44. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

_mdr_i 

load_reg 
stop 




start: 



oo 

10 



7 8 9 A B C D 



01 


05 


0B 


02 


FF 


03 























































OF 
IF 



F0 



FF 



0 1 



4 



7 8 



A B C D E 



344 



A simple 8-bit CPU: version "A' 



Figure 8.45. Data bus after the execution of the load example above. Video: ogv 
http://www.youtube. com/watch ?v=AXUSrH49cF49w 





s 


131 


OIQIMI 




IS 


0 


|ri||ri|ri 

MM 1 - 


1 I 1 


i ii 




16 | 10 


16 ^ 1 10 r 



sap 




« 



8.2.2 Storing instructions 

The following example shows the usage of the instructions store_ref and 
store_reg: 



begin macrocode @ 0 
start : 

load_ref #data_l 
store_ref #data_2 
move_mdr_i 
store_reg 

stop : 

stop 

data_l : 

.byte 15 

data_2 : 

.byte 0 



A simple 8-bit CPU: version "A' 



345 



end 



The MDR loads the value contained in memory at the address matching the label 
data_l (that is, it loads the value 15). Then, the MDR content is written in memory 
at the address represented by the label data_2 (that is, the value 15 is written at the 
address 8, replacing the previous zero). Then, the MDR is copied to / (that is, the 
/ register will get the value 15). Then, at the address pointed by /, the memory is 
written with the value contained inside MDR (that is, the value 15 is written at the 
address 15). 

Figure 8.47. RAM memory before the execution. 

load_ref 

#data_l 

store_ref 

- #data_l 




move 
- store 



start: 



mdr_i 

_reg 
stop 

8 9 



A B C D 



00 


01 


07 


03 


07 


0B 


04 


FF 


OF 


00 
















10 












































FO 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



346 



A simple 8-bit CPU: version "A' 



Figure 8.48. RAM memory after the execution of the store_ref instruction. 

load_ref 

#data_l 

store_ref 
#data_2 

move_mdr_i 

store_reg 
-stop 




start: 



8 9ABCDEF 



00 


01 


07 


03 


08 


0B 


04 


FF 


OF 


OF 
















10 












































F0 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



A simple 8-bit CPU: version "A' 



347 



Figure 8.49. RAM memory at the end. 

load_ref 

#data_l 

store_ref 

- #data_l 




move 
- store 



start: 



mdr_i 

_reg 
stop 



8 9 A B C D 



00 


01 


07 


03 


07 


0B 


04 


FF 


OF 


OF 














OF 


10 












































F0 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



IF 



FF 



348 



A simple 8-bit CPU: version "A' 



Figure 8.50. Data bus after the execution of the store example above. Video: 
http://www.youtube. com/watch 7v=lHxx3SR56hE56 



ogv 



IHIIIII | 



E SEE 



lg I 10 





0 


E 


>-'!-' 1-' 




10 


Fl 


mm 


1 III 


1 Mill 


1 


16 


1 « 


16 


| 10 r 



bi 


data 


b 1 ,'.' 


elk 


IR 


Clr 




bus 






br ftddr b 1 . 1 ,' 



D 



br data bw 
CU: MAR clr 

bus 



-D 



-D 



1 ml 


in 


1 


mi 




16 ■ 1 10 



br data bw 
;U MDR Clt 
bus 



—O 



Clr Cik " 

bvr data br 



clear 



-D 



\J\J h 



B 



Mil 



i t 4- 



-D 



br data 






Inc 


cm pc 






clr 


bus 





D 



-D 



"ffl 

'' Be 1 

MDOD 



8.3 Version "A3": general purpose registers 

On the third subversion of the simple CPU two registers are added, without any par- 
ticular purpose: A and B. These registers are made in the same way as /, MDR, MAR 
and IR. 



A simple 8-bit CPU: version "A" 

Figure 8.51. Simple CPU version "A3". 



349 




Inside the code that describes the microcode word fields, the following fields are 
added: they are used specifically to manage the A and B registers: 



field 


a_br [17] ; 


// A 


< — bus 


field 


a_bw [18]; 


// A 


— > bus 


field 


b_br [27] ; 


// B 


< — bus 


field 


b_bw [28]; 


// B 


— > bus 



Inside the opcode list there are new instructions and the same is for the microcode 
description: 



op move_mdr_a { 








map move_mdr_a : 


5; 


// move 


MDR to A 


+0 [7 : 0] =5; 








operands op_0; 

}; 








op move_a_mdr { 








map move_a_mdr : 


6; 


// move 


A to MDR 



350 



A simple 8-bit CPU: version "A' 



+0 [7 : 0] =6; 








operands op_0; 

}; 








op move_mdr_b { 
map move_mdr_b : 
+0 [7 : 0] =7; 


7; 


// move 


MDR to B 


operands op_0; 

}; 








op move_b_mdr { 
map move_b_mdr : 
+0 [7 : 0] =8; 


8; 


// move 


B to MDR 


operands op_0; 

I; 









begin microcode @ 0 










move_mdr_a : 










a_b r md r _b w ; 




// 


A <- 


— MDR 


ctrl_start Ctrl. 


_load; 


// 


CNT 


<— o 


// 










move_a_mdr : 










md r _b r a_b w ; 




// 


MDR 


< — A 


ctrl_start Ctrl. 


_load; 


// 


CNT 


<— o 


// 










move_mdr_b : 










b_b r md r _b w ; 




// 


B <- 


— MDR 


ctrl_start Ctrl. 


_load; 


// 


CNT 


<— o 


// 










move_b_mdr : 










md r _b r b_b w ; 




// 


MDR 


< — B 


ctrl_start Ctrl. 


_load; 


// 


CNT 


<— o 


end 











A simple 8-bit CPU: version "A' 



351 



Figure 8.55. Match between the contents of the memory that represents the mi- 
crocode (the couple of memory banks ml and m2 inside the control unit) and the 
microcode description itself. 



1 





1 












\ 


if 




















\ X \ 


1 














r 




/ /> 




b35 


b34 


b33 


b32 


Ml 


b30 


b29 


b28 


h27 


b26 


b25 


b24 


b23 


b22 


b21 


b20 


bl9 


hl8 


bl7 


111 6 


his 


bl4 


bl3 


bl2 


hi 1 


blO 


b9 


bS 


b7 


1* 


b5 


b4 


b3 


h2 


bl 


hi) 


move_mdr_a: 






































1 


0 


0 


0 








1 














0 






:: 












































:.) 


:.) 






















:.) 




1 


l 



move a mdr: 
























a 


a 


a 








l 




a 


a 












l 


a 


a 








a 




















a 












a 


■ 


a 












a 


a 














a 


a 








a 




l 


l 



move_mdr_b: 


















1 








a 










a 




a 


a 


a 








l 




a 


a 








a 


0 














































c 


c 


c 


a 


a 






0 


c 


c 


0 


a 


a 


c 


a 


l 


l 



move b mdr: 
















1 






















0 


C 


c 




a 


a 






1 


C 


C 


0 


a 


0 




a 








c 


C 






C 


C 






c 


C 




c 


c 


C 






C 


c 




: 


c 


c 






C 






c 


0 








0 




1 


1 




h?5 


b34 


b33 


b32 


hJI 


b30 


h29 


l>28 


h27 


b26 


b25 


h24 


h23 


b22 


b21 


b20 


bl9 


hl8 


bl7 


bl6 


his 


hl4 


bl3 


h!2 


hll 


hlO 


W 


bS 


b7 


I* 


bS 


b4 


b3 


h2 


bl 


bO 



Table 8.56. Macroinstructions added for this version of the simple CPU. 



Syntax 


Description 


move_mdr_a 


It copies the MDR content into the A register. 


move_a_mdr 


It copies the A content into the MDR register. 


move_mdr_b 


It copies the MDR content into the B register. 


move_b_mdr 


It copies the B content into the MDR register. 



It follows a macrocode example where some data is loaded from memory and stored 
inside the A and B registers: 

begin macrocode @ 0 
start : 

load_ref #data_l 
move_mdr_a 
load_ref #data_2 



352 



A simple 8-bit CPU: version "A' 



stop : 
data_l 
data_2 
end 



move_mdr_b 
stop 
byte 17 
byte 11 



It loads into the MDR register the value 17 (located in memory at the address match- 
ing the label data_l) and then it copies the loaded value into the A register. Then it 
does the same with the value 1 1 (located in memory at the address matching the label 
data_2) that is copied into the B register. The full source file should be available at 
attachments/xcpu/xcpu-a3.gm . 

Figure 8.58. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

move_mdr_a 

load_ref 
#data_2 

move_mdr_b 

^stop 




start: 



8 9 A B C D E 



00 


01 


07 


05 


01 


08 


07 


FF 


11 


0B 
















10 












































FO 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



A simple 8-bit CPU: version "A' 



353 



Figure 8.59. Data bus after the execution of the above example. Video: ogv http:/ 
/www.youtube. com/watch ?v=9q VsCKmxcdk 




At the moment, the simple CPU under development is not able to copy the content of 
a register to another one, without the mediation of the MDR register. In other words, 
there is no move_a_b instruction and the intended action is obtained instead with two 
steps: move_a_mdr and then move_mdr_b. That is made to keep the project very 
simple as long as possible. 

8.4 Version VV A4": ALU 

The fourth subversion of the simple CPU receives an ALU (arithmetic-logic unit), 
including the ability to shift and rotate bits, but at the moment there is no management 
of flags (there are no carry, sign, zero and overflow flags). 



« 



354 



A simple 8-bit CPU: version "A' 



Figure 8.60. Simple CPU version "A4". 




stop 



3029 
2827 

23:19 
18:17 
15:15 ■ 
14:13 
12:11 
10:9 

4:2 



Clk CTRL Clr 



br dala bw 



Clk IR Clr 



br Addr bw 
RAM 
bus 



bus 

r] Clr ' Clk « 
bw data br 



br data bw 
^Clk MAR Clr ^ 
bus 



bus 

^ Clr B Clk|7 
bw data br 



br data bw 
— Clk MDR Clr ^ 
bus 

ir 



ALU F „ -r- 



br data bw 

In 

; cik pc 

c 

bus 
It 



bus 

^ Clr A Clk 
bw data br 



dear 



A simple 8-bit CPU: version "A' 



355 



Figure 8.61. The ALU structure: the red lines have an 8-bit size, while the black 
lines are single bit ones. 




f=0: NOT A (Carry and Overflow unchanged) 

f=1 : A AND B (Carry and Overflow unchanged) 

f=2: A OR B (Carry and Overflow unchanged) 

f=3: A XOR B (Carry and Overflow unchanged) 

f=4: logic shift left 

f=5: logic shift right 

f=6: arithmetic shift left 

f=7: arithmetic shift right 

f=8: rotation left 

f=9: rotation right 

f=10: rotation left with carry 

f=1 1 : rotation right with carry 

f=12: A plus B with carry 

f=13: A minus B with carry 

f=14: A plus B with no carry 

f=1 5: A minus B with no carry 



356 



A simple 8-bit CPU: version "A" 



Figure 8.62. Module shift, responsible to make bit shifts and bit rotations. 



roc 

V 



ro 

V 



Ir 

V 



A 

V 



la 

V 




/' 8 



1_ 

0" 



0 



□ 



V 
Co 



o s 



A simple 8-bit CPU: version "A" 

Figure 8.63. Module sh, contained inside the shift module, to shift the bits. 



357 



0=left 
1=right 



lin>- 

left in 



lout 

left out 



carry 

left 

side 



0=logic shift 

1 =arithmetic shift 



[3] 



[1] 



[3] 



[3] 



1 0 



j a 



[4] 



mux / \ mux 



mux , 



, mux 



mux , 



0 



[2] 



overflow 



right out 



right in 



mux , 



. mux 



□ 



[1] Arithmetic rotation check: 

- the shift is arithmetic; 

- the shift is to the right; 

- the most significant bit bust be equal to one. 
[2] Overflow check: 

- the shift is arithmetic; 

- the most significant bit is not changed. 

[3] Connection to the most significatn bit or to the sign bit. 
[4] Connection to the least significant bit. 
[CI] Carry to the left side: 

- it is a left shift; 

- the most significant bit was equal to one (negative). 
[Cr] Carry to the right side: 

- the shift is to the right; 

- the least significant bit was equal to one. 



carry 
right 
side 



358 



A simple 8-bit CPU: version "A' 



Figure 8.64. Module as, which is able to add or subtract the inputs. 



Co < 

carry out 
borrow out 



f=0 

calculate the sum (A + B) producing the carry request if necessary; 
Ci and Co mean, respectively, carry in and carry out. 
f=1 

calculate the subtraction (A - B) producing the borrow request if necessary; 
Ci and Co mean, respectively, borrow in and borrow out. 



/a 



a b 
co fa ci 
s 




a b 
co fa ci 
s 




a b 
co fa ci 
s 













a b 
fa 



a b 
, fa 



a b 
, fa 



a b 
, fa 



^loicji-^coro-io 



a b 

~t fa 



overflow 



V 



carry in 
borrow in 



0 



Inside the code that describes the microcode word fields, the following fields are 
added: they are used specifically to manage the ALU. Please notice that the ALU has 
the ability to write to the bus, but it cannot read from the bus, because the ALU does 
not receive data from the bus; moreover, the ALU requires to control the function 
applied to the input data. 



field alu_f [22 : 19] ={ 
not_a=0 , 
a_and_b=l , 
a_or_b=2 , 
a_xor_b=3 , 
logic_shif t_lef t=4 , 
logic_shif t_r ight = 5 , 
arith_shif t_lef t = 6 , 
arith_shif t_r ight = 7 , 
rotate_lef t=8 , 
rotate_right=9, 



A simple 8-bit CPU: version "A' 



359 





rotate_carry_ 


_left=10, 




rotate_carry_ 


_right = l 1 , 




a_plus_b_carry=12 , 




a_minus_b_borrow=l 3 , 




a_plus_b=14 , 




}; 


a_minus_b=l 5 




J ' 

field 


alu_bw [23] ; 


// ALU — > bus 


field 


f l_ar [24] ; 


// FL < — ALU 



The field fl_ar can be ignored at the moment, because it will be useful only in the 
next version of the CPU, when the status flags will be managed. Currently, inside the 
microcode, there are references to the field fl_ar, because in the next CPU version 
there will be the register FL, which currently is missing. There are many new opcode 
for the ALU functions: 



r\ir\ in r~\ "H J 
U|J I1U L 1 

map not : 32; 
+ u L / . u J — jz, 


// A 


= NOT A 


operands op_0; 

}; 






op and { 

map and : 33; 
+0 [7 : 0] =33; 


// A 


= A AND B 


operands op_0; 

}; 






op or { 

map or : 3 4; 
+0 [7 : 0] =34; 


// A 


= A OR B 


operands op_0; 

}; 






op xor { 

map xor : 35; 
+0 [7 : 0] =35; 


// A 


= A OR B 


operands op_0; 

}; 







360 



A simple 8-bit CPU: version "A' 



op lshl { 

map lshl : 36; 
+0 [7 : 0] = 3 6; 
operands op_0; 

}; 


// A 




A « 1 


op lshr { 

map lshr : 37; 
+0 [7 : 0] = 37; 
operands op_0; 

}; 


// A 




A » 1 


op ashl { 

map ashl : 38; 
+0 [7 : 0] =38; 
operands op_0; 

}; 


// A 




A « 1 


op ashr { 

map ashr : 39; 
+0 [7 : 0] =3 9; 
operands op_0; 

}; 


// A 




+/-A » 1 


op rotl { 

map rotl : 4 0; 
+0 [7 : 0] =4 0; 
operands op_0; 

}; 


// A 




A rotate left 


op rotr { 

map rotr : 41; 
+0 [7 : 0] =41; 
operands op_0; 

}; 


// A 




A rotate right 


op add { 

map add : 4 6; 
+0 [7 : 0] =46; 
operands op_0; 


// A 




A + B 



A simple 8-bit CPU: version "A' 



361 



}; 

op sub { 






map s ub : 4 7; 




// A = A - B 


+0 \1 : 01 = 4 7; 






operands op_0; 

}; 








begin microcode @ 0 






not : 






a_br alu_f=not_a alu_bw fl_ar; 




// A < — NOT A 


ctrl_start ctrl_load; 




// CNT < — 0 


// 






and : 






a_br alu_f =a_and_b alu_bw fl_ar; 




// A < — A AND B 


ctrl_start ctrl_load; 




// CNT < — 0 


// 






or : 






a_br alu_f=a_or_b alu_bw fl_ar; 




// A < — A OR B 


ctrl_start ctrl_load; 




// CNT < — 0 


// 






xor : 






a_br alu_f =a_xor_b alu_bw fl_ar; 




// A < — A XOR B 


ctrl_start ctrl_load; 




// CNT < — 0 


// 






lshl : 






a_br alu_f =logic_shif t_lef t alu_bw 


fl_ 


ar; // A < — A « 1 


ctrl_start ctrl_load; 




// CNT < — 0 


// 






lshr : 






a_br alu_f =logic_shif t_right alu_bw 


fl 


_ar; // A < — A » 1 


ctrl_start ctrl_load; 




// CNT < — 0 


// 






ashl : 






a_br alu_f =arith_shif t_lef t alu_bw 


fl_ 


.ar; // A < — A*2 


ctrl_start ctrl_load; 




// CNT < — 0 



362 



A simple 8-bit CPU: version "A' 



// 








ashr : 








CL U -L 


all, f 
CL _L Li -L 


— a y*i "t"Vi cr In ~i *F +- t — i rr V~i "t~~ ^lii lr\ TaT 

— CL J L L- 1 1 o 1 1 _L -L L_ I_ _HJ 1 1 L- CL _L U. U W 


J L CL J_ / / / T± ^ ■**/ ^ 


Ct 


_st art 


CLi J_ lOaQ^ 


/ / l—IV 1 <• — U 


// 
// 








rot 1 : 








pi V> T~ 
Ct J_ 


sin f 

CL _L Li -L 


= T" o "h ;=i "h p> 1 p> ~F "h pilii Viw "Fl ;^ t° • 

1 U t U L C _L<3-J_L- CL _L LL S*J W J L CL J_ f 


// A < A rot l&fii 


"H t~ 1 
L- L -L _L_ 


_o L a L L 


U L J! X _l_ U a. UL A 


// fJJT <~ f) 


// 
// 








rotr : 








CL U -L 


sin f 

Cl _L Li -L 


— t'^'K^'Ho t — i n-ji +- ^lii Tat "Pi ^ t~ 

— J_ KJ L- CL L- *3 J_ ±U 11L CL _L U. U W J L CL -L 




ct r 1_ 


_st art 


(~* \~ \ 1 s~\ in • 
LLI X _!_ UdU. , 


// CTJT /I 

/ / Oiv x V 1/ 


// 

/ / 








add : 








d U -L 


sin f 

CL _L LL -L 


— ^ t~> 1 n c V> 3 1 1 1 V> TnT "Pi "d >-~ • 
cl piUo U a± U UW J L CL J_ ^ 




ct rl_ 


_st art 


Ct ITX lOau, 


// Civ J. < C 


// 
// 








sub : 








a_br 


alu_f 


=a_minus_b alu_bw fl_ar; 


// A < — A - B 


pf r 1 




O L- J_ _L _L \J CxkJ. f 


// CNT < — 0 


end 









A simple 8-bit CPU: version "A' 



363 



Figure 8.68. Match between the contents of the memory that represents the mi- 
crocode (the couple of memory banks ml and m2 inside the control unit) and the 
microcode description itself. 



and: 



or: 



xor: 



si V 



N 4 V \i 



1 H ^ 



-o 



2 5 



•07 s3y 



iff/ 



o . 

C / 

a 



4/ 



h3S hJ4 h33 bj2 bjl h30 h29 b28 h27 h26 h2j h24 h23 b22 b2l h2(.) his) his h 17 hlb bis h!4 h!3 h!2 bll blO b9 



r t ? />•' 

b7 b6 b5 b4 b3 b2 bl bO 



reof: 


0 
















0 






1 


1 


0 


0 


0 


0 


0 


1 






0 








0 


0 








































0 


















































1 


1 













D 








1 


0 


1 


1 


0 


0 


0 


1 




1 


























1 








0 


































1 




































1 


1 
























1 


1 


0 


0 


1 


0 




1 




































(J 










































0 










0 
















1 


1 


0 
















0 






1 


1 


0 


0 


1 


1 




1 






0 










0 




































0 


















0 








0 










0 
















1 


1 



Ishl: 


0 
















0 






1 


1 


0 


1 


0 


0 


0 


1 














0 


0 






















0 
















0 


















0 
















0 


0 
















1 


1 



Ishr: 
















1 








1 


1 


0 


1 


0 


1 




1 






























1 








0 
















0 


















0 








0 








0 


: 
















1 


1 




b35 


b34 


b33 


b32 


Ml 


b30 


b29 


b28 


b27 


H26 


b25 


b24 


b23 


b22 


h2l 


b20 


bl9 


bl8 


h!7 


M6 


bl5 


b!4 


bI3 


h 12 


bll 


blO 


b9 


b8 


b7 


b6 


h5 


b4 


b3 


b2 


bl 


bll 



0=not A 
1=Aand B 
2=A or B 
3=A xor B 
4=A « 1 
5=A » 1 
6=A « 1 arith 
7=A » 1 arith 
8=A rot left 
9=A rot right 
A=A rot carry left 
B=A rot carry right 
C=A plus B carry 
D=A minus B borrow 
E=A plus B 
F=A minus B 



\4> 



364 



A simple 8-bit CPU: version "A' 



% 

-o 



-o; 



M |f t 



a -Q ; O / 



4' 



b35 b34 b33 b32 b31 b30 b29 b28 b27 b26 b25 b24 b23 b22 b21 b20 bl9 bl8 bl7 bl6 bl5 bl4 bl3 bl2 bll blO b9 



O j 

c 



b7 b6 b5 b4 b3 b2 bl bO 



ashl: 
























1 


1 


0 


1 


1 


0 




1 












































0 
































0 


0 


















0 










1 


1 



ashr: 






i 








i 










l 


l 


0 


l 


l 


1 




1 






1 








0 


1 




c 




0 


1 










































0 


0 


0 




0 




0 














0 


0 




0 






1 


1 





0 






0 




0 




3 


0 




0 


1 


1 


1 


0 


0 


0 




1 






































0 




















!J 




0 










0 


































1 


1 



rotr: 






i 








c 


1 








1 


1 


1 


0 


0 


1 




1 






c 




c 






c 














c 




















0 




















0 










0 




0 


0 




0 




0 


0 




0 




0 


1 


1 



























1 


1 


1 


1 


1 


0 




1 


0 








































i 








c 


1 






















































1 


1 



sub: 






1 








1 










1 


1 


1 


1 


1 


1 




1 














D 






1 






1 




c 


































































o 










1 


1 




b35 


b34 


b33 


b32 


Ml 


b30 


H29 


b28 


b27 


b26 


b25 


b24 


b23 


b22 


H2I 


b20 


bi9 


bl8 


b!7 


bib 


bis 


bl4 


bu 


b!2 


bll 


blO 


b9 


b8 


h7 


bb 


h5 


b4 


b3 


b2 


bl 


bO 



4 



0=not A 
1=Aand B 
2=A or B 
3=A xor B 
4=A « 1 
5=A » 1 
6=A « 1 arith 
7=A » 1 arith 
8=A rot left 
9=A rot right 
A=A rot carry left 
B=A rot carry right 
C=A plus B carry 
D=A minus B borrow 
E=A plus B 
F=A minus B 



?4% 



Table 8.69. The new macroinstructions for the current CPU version. Some C 
language notation is used to simplify the description. 



Syntax 


Description 


not 


A=~A 

One's complement of A. 


and 


A=A&B 

It is assigned to A the result of A AND B, bit per 
bit. 


or 


A =A\B 

It is assigned to A the result of A OR B, bit per bit. 



A simple 8-bit CPU: version "A' 



365 



Syntax 


Description 


xor 


A=A A B 

It is assigned to A the result of A XOR B , bit per bit. 


lshl 


A = A « 1 

It is assigned to A the logic shift left of one bit from 
the previous value of A . 


lshr 


A = A » 1 

It is assigned to A the logic shift right of one bit from 
the previous value of A . 


ashl 


A = A « 1 

It is assigned to A the arithmetic shift left of one bit 

A \- 1U iiJ JlCllvvf »«\_» M. Wllv HI 1 1.11111 V H V Ulllll Ivll V^-l Vllv l^lv- 

from the previous value of A (it is the same as the 
logic shift left). 


ashr 


A = A » 1 

Tt is assigned to A the arithmetic shift ri?ht of one 

lu UuulSlllvLi Iv J. m. Hlv Clllllllllvl.lv Ollll V, 11 will VI vllv 

bit from the previous value of A (the sign is kept the 
same). 


rot 1 


It is assigned to A the result of one bit rotation left 
from the original value of A . 


rot r 


It is assigned to A the result of one bit rotation right 
from the original value of A . 


add 


A =A + B 

it is assigned to A the result of the sum of A and B, 
without considering the previous carry. 


sub 


A=A - B 

it is assigned to A the result of the subtraction of A 
and B, without considering the previous borrow. 



The following sections offer various examples, where the use of all the new instruc- 
tions is shown. 



366 



A simple 8-bit CPU: version "A' 



8.4.1 Instruction "not" 

Listing 8.70. Macrocode example to experiment the not instruction: a value is 
loaded from the memory to the A register, then the one's complement is cal- 
culated and put into the A register. The complete source should be available at 
attachments/xcpu/xcpu-a4-not.gm . 

begin macrocode @ 0 
start : 

load_ref #data_l 

move_mdr_a 

not 

stop : 

stop 

data_l : 

.byte 17 

end 



A simple 8-bit CPU: version "A" 



367 



Figure 8.71. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

mo ve_mdr_a 

not 
- stop 




start: 



7 8 



A B C D E 



00 


01 


05 


05 


20 


FF 


11 






















10 












































F0 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



368 



A simple 8-bit CPU: version "A' 



Figure 8.72. Data bus after the execution of the above example. Video: ogv http:/ 
/www.youtube.com/watch?v=x5Vnhd72vh728 



iiiiiiini [F] 



B EBB 



oscillator 



SL n-0 



IS 



aim ran 



-D 



br data bw 
elk IR clr 



br Addr ttir 



br data bw 
cJi MAR clr 





bua 


Clr 


B CUc 


bw 


cUt h br 



IJ CIJIJ 



2_ 



Sl| GIGS 



br data bw 
pdclJi MDR clr 




D 



br data bw 
I no 

cut n 



PC 



-D 





bus 




Fi 


ALU 

B A 


Fo 
£ 



bus 

Clr A Cl>. 
b'. 1 ,' 6 it a b r 



HOLD 



signs 



8.4.2 Instruction "and" 

Listing 8.73. Macrocode example to experiment the and instruction: two values 
are loaded from the memory into the registers A and B, then the binary AND 
is calculated and saved inside the A register. The complete source should be 
available at attachments/xcpu/xcpu-a4-and.gm . 



begin 


macrocode @ 0 


start 






load_ref #data_l 




move_mdr_a 




load_ref #data_2 




move_mdr_b 




and 


stop : 






stop 



A simple 8-bit CPU: version "A' 



369 



(i Fl t" R 1 • 








. byte 


17 


data 2 : 








. byte 


11 


end 







Figure 8.74. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

move_mdr_a 

load_ref 
#data_2 

move_mdr_b 

and 

^stop 




start: 



9 A B C D E F 



00 


01 


08 


05 


01 


09 


07 


21 


FF 


11 


0B 














10 












































F0 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



370 



A simple 8-bit CPU: version "A' 



Figure 8.75. Data bus after the execution of the above example. Video: ogv http:/ 
/www.youtube. com/watch ?v=2ra 7SHxBvYY 



iiiiiiii 



F 



B SHE 



r-QZP 



IZZIIZZ 



:zze 



iiiiiiiiiI 




•c 



IGJIPIQIIJI oi|D 



-D 



IL -rD 



stop 



br data bur 
-+\clk IR Clr 
bus 



-D 



D 



br ftddr bw 



00H 



hi GIIJIJ 



■o 



br >3 ;t-s b 1 , 1 .' 
prjclJt MAR clr 
bus 



-D 



;lr elk 
bw data br 



br .iit.5. bw 



r+ elk MDR clr 



■D 



— D 



b l d at h bw 



8 ::: sie 



-D 



r 



ALU *n =- 



bus 

Clr A Cli 
bw data br 



HPCD 



-D 



DODO 



_ 



CD 



ran 



-D 



LH 



8.4.3 Instruction "or" 

Listing 8.76. Macrocode example to experiment the or instruction: two values 
are loaded from the memory into the registers A and B, then the binary OR 
is calculated and saved inside the A register. The complete source should be 
available at attachments/xcpu/xcpu-a4-or.gm . 



begin 


macrocode @ 0 


start 






load_ref #data_l 




move_mdr_a 




load_ref #data_2 




move_mdr_b 




or 


stop : 






stop 



A simple 8-bit CPU: version "A' 



371 



(i Fl t" R 1 • 








. byte 


17 


data 2 : 








. byte 


11 


end 







Figure 8.77. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

mo ve_mdr_a 

load_ref 
#data_2 

-move mdr b 



start: 




00 


01 


08 


05 


01 


09 


07 


22 


FF 


11 


0B 














10 












































F0 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



372 



A simple 8-bit CPU: version "A' 



Figure 8.78. Data bus after the execution of the above example. Video: ogv http:/ 
/www.youtube.com/watch?v=7E-2uA6fVoY 




0100 ^obO 



D 



B ODD 



br Addr bw 
RAM 





bus 


Clr 


1 Clk 


bv 


data br 



be data bw 
Cli MAR clx 



-D 



00H 0 



Clr CUt 
bw data, br 



-D 



IT 

2_ 



0 



br data bw 
cxk MDR Clr 
bus 



— D 



D 



br data 


bw 




I lie 


CJk pc 






C l£ 


bus 





r 



ALU Fn — 



bw B f 



-D 



3IO0g 



JTO- 



bus 

Clr A Cli 

bw data br 



hold 



D 



ODD 0 



_ 



u-o. 



■a 



mm 



D 



IS 



II II I 



8.4.4 Instruction "xor" 

Listing 8.79. Macrocode example to experiment the or instruction: two values 
are loaded from the memory into the registers A and B, then the binary XOR 
is calculated and saved inside the A register. The complete source should be 
available at attachments/xcpu/xcpu-a4-xor.gm . 



begin 


macrocode @ 0 


start 






load_ref #data_l 




move_mdr_a 




load_ref #data_2 




move_mdr_b 




xor 


stop : 






stop 



A simple 8-bit CPU: version "A' 



373 



(i Fl t" R 1 • 








. byte 


17 


data 2 : 








. byte 


11 


end 







Figure 8.80. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

move_mdr_a 

load_ref 
#data_2 

move_mdr_b 

xor 

^stop 




start: 



9 A B C D E F 



00 


01 


08 


05 


01 


09 


07 


23 


FF 


11 


0B 














10 












































F0 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



374 



A simple 8-bit CPU: version "A' 



Figure 8.81. Data bus after the execution of the above example. Video: ogv http:/ 
/www.youtube. com/watch ?v=TuzknbyeabQ 



H-nr 



DiOS cnpB 



br ftddr but 



br data bw 
Clk MAR cix 
bus 



2 



T 



-^|c.D: MDR Clr 
bus 



br data bw 

mo 



bus 




Fi ^ 


Fo 


S A 


r 



1.11 1" 

,1. A 
bw data b r 




31 IB 



HDLD 



8.4.5 Instruction "Ishl" and "Ishr" 

Listing 8.82. Macrocode example to experiment the logic shift instructions: a 
value is loaded from the memory to the A register and a left shift is done, up- 
dating the value of A. Then the result is copied into B, before another value is 
loaded to calculate the right shift. The complete source file should be available at 
attachments/xcpu/xcpu-a4-lsh.gm . 

begin macrocode @ 0 
start : 

load_ref #data_l 

move_mdr_a 

lshl 

move_a_mdr 
move_mdr_b 
load_ref #data_l 



A simple 8-bit CPU: version "A' 



375 



stop : 

data_l 

end 



move_mdr_a 
lshr 

stop 

.byte 17 



Figure 8.83. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

move_mdr_a 
lshl 

move_a_mdr 
move_mdr_b 

load_ref 

1 

mdr a 




start: 



move_ 
lshr 
stop 

B C D E F 



00 


01 


OB 


05 


24 


06 


07 


01 


0B 


05 


25 


FF 


11 










10 












































FO 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



376 



A simple 8-bit CPU: version "A' 



Figure 8.84. Data bus after the execution of the above example. Video: ogv http:/ 
/www.youtube. com/watch 7v=pkRfWYqGeB4 



IIIIMII 



zzze 



u s ci lis. tor 




ca CTRL clr 



<:tnf:i 



IS 



ibi loiijy 



br data bw 
Cli IR Clr 
bus 



D 



O 



br Addr bw 

rah 

t.ll.L- 



clr cli 
bw data br 



IJ CIIJIJ 



■D 



1 k MAR c 

bus 



-D 



□an o 





bus 


C Ir 


B CJH 


bw 


data br 



-D 



□BO 



-H-D 



br data bw 
elk MDR Clr 
bus 



— D 



-D 



br data bw 
Ino 



-D 



jr 



-D 



aniju 



Clr CUt 
bw data br 



Hririni 



IS 



o ay e 



-□ 



001 D 



D 



8.4.6 Instruction "ashl" and "ashr" 

Listing 8.85. Macrocode example to experiment the arithmetic shift instructions: 
a value is loaded from the memory to the A register and a left shift is done, 
updating the value of A. Then the result is copied into B, before another value is 
loaded to calculate the right shift. The complete source file should be available at 
attachments/xcpu/xcpu-a4-ash.gm . 

begin macrocode @ 0 
start : 

load_ref #data_l 

move_mdr_a 

ashl 

move_a_mdr 
move_mdr_b 
load_ref #data_l 



A simple 8-bit CPU: version "A' 



377 



stop : 

data_l 

end 



move_mdr_a 
ashr 

stop 

.byte 143 



Figure 8.86. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

move_mdr_a 
ashl 

move_a_mdr 
move_mdr_b 

load_ref 

1 

mdr a 




start: 



move_ 
^ashr 

stop 

B C D E F 



00 


01 


OB 


05 


26 


06 


07 


01 


0B 


05 


27 


FF 


8F 










10 












































F0 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



378 



A simple 8-bit CPU: version "A' 



Figure 8.87. Data bus after the execution of the above example. Video: ogv http:/ 
/www.youtube.com/watch ?v=3rvRl WvWdlk 




8.4.7 Instruction "rotl" and "rotr" 

Listing 8.88. Macrocode example to experiment the rotation instructions: a value 
is loaded from the memory to the A register and a left rotation is done, updating 
the value of A. Then the result is copied into B, before another value is loaded 
to calculate the right rotation. The complete source file should be available at 
attachments/xcpu/xcpu-a4-rot.gm . 

begin macrocode @ 0 
start : 

load_ref #data_l 

move_mdr_a 

rot 1 

move_a_mdr 
move_mdr_b 
load_ref #data_l 



A simple 8-bit CPU: version "A' 



379 



stop : 

data_l 

end 



move_mdr_a 
rot r 

stop 

.byte 17 



Figure 8.89. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

move_mdr_a 

rotl 

move_a_mdr 
move_mdr_b 

load_ref 

1 

mdr a 




start: 



move_ 
^rotr 

stop 

B C D E F 



00 


01 


OB 


05 


28 


06 


07 


01 


0B 


05 


29 


FF 


11 










10 












































F0 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



380 



A simple 8-bit CPU: version "A' 



Figure 8.90. Data bus after the execution of the above example. Video: ogv http:/ 
/w ww.youtube. com/watch ?v=KCi8n 6bnLQo 




8.4.8 Instruction "add" 

Listing 8.91. Macrocode example to experiment the addition instruction: two val- 
ues are loaded from the memory into the registers A and B, then the addition is 
calculated and saved inside the A register. The complete source should be avail- 
able at attachments/xcpu/xcpu-a4-add.gm . 



begin 


macrocode @ 0 


start 






load_ref #data_l 




move_mdr_a 




load_ref #data_2 




move_mdr_b 




add 


stop : 






stop 



A simple 8-bit CPU: version "A' 



381 



(i Fl t" R 1 • 








. byte 


17 


data 2 : 








. byte 


11 


end 







Figure 8.92. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

move_mdr_a 

load_ref 
#data_2 

move_mdr_b 

add 

^stop 




start: 



9 A B C D E F 



00 


01 


08 


05 


01 


09 


07 


2E 


FF 


11 


0B 














10 












































F0 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



382 



A simple 8-bit CPU: version "A" 



Figure 8.93. Data bus after the execution of the above example. Video: ogv http:/ 
/www.youtube. com/watch 7v=QQJwz2yVwA8 




« 



8.4.9 Instruction "sub" 

Listing 8.94. Macrocode example to experiment the subtraction instruction: two 
values are loaded from the memory into the registers A and B, then the subtrac- 
tion (A -B) is calculated and saved inside the A register. The complete source 
should be available at attachments/xcpu/xcpu-a4-sub.gm . 



begin macrocode @ 0 
start : 

load_ref #data_l 

move_mdr_a 

load_ref #data_2 

move_mdr_b 

sub 



stop : 



stop 



A simple 8-bit CPU: version "A' 



383 



(i Fl t" R 1 • 








. byte 


17 


data 2 : 








. byte 


11 


end 







Figure 8.95. RAM memory content: the memory cells marked with "xx" have an 
unknown and unspecified value. 

load_ref 

#data_l 

move_mdr_a 

load_ref 
#data_2 

move_mdr_b 

sub 

^stop 




start: 



9 A B C D E F 



00 


01 


08 


05 


01 


09 


07 


2F 


FF 


11 


0B 














10 












































F0 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



OF 
IF 

FF 



384 



A simple 8-bit CPU: version "A" 



Figure 8.96. Data bus after the execution of the above example. Video: ogv http:/ 
/www.youtube. com/watch ?v=VRd8HJbK_ Y 



(nnnn)|F 



BHHH 



,_n:iz:::" 



.JZZZIZ Z 



rr 



-"-rD 



re? ime 




r~m 



stop 



br data bw 
pfjcik IR Cli 
bus 



-D 



i rr 



-D 



b r Addr bw 

flak 



y bud 



t-D 



UL 



br data bw 
-dcik MAR clr 



-D 



clr - elk 
bw data br 



SOB 0 



Clr " Cli 
bw data br 



br data bw 
pdcli MDR clr 



— D 



bl J it s t".'.' 

Xnc 



JlO" 



-D 



r 



ALU .„ — 



•D 



at 



mm s 



:lr " oil 

bw data br 



-a 



SOB 0 



HCffi 



D 



JLI 



« 



8.5 Version 7\5": flags 

The fifth version of the simple CPU has a new special register: FL, used to store the 
status flags. With the FL register the ALU can use previous carry (or borrow) for 
calculations and for rotations. 



A simple 8-bit CPU: version "A" 



385 



Figure 8.97. The simple CPU version "A5". 




The FL register can communicate with the bus, but it has an additional input, Fi, 
which receives the updated status from the ALU. On the other hand, the output Fo 
sends to the ALU the current status of flags. The control input ar (ALU read) is used 
to let the FL register load its value from the ALU. 



386 



A simple 8-bit CPU: version "A' 



Figure 8.98. Internal structure of the FL register: the eight aligned modules are 
D flip-flops. The diagram on the right is a compact version of the same circuit. 



* 




bus 




Clr 


FL 


Clk 


Fi 




Fo 


bw 


br 


as 


+ 


t 


t 




dd 





Preset 




Q 




D 


Q 




Clk 




Clear 





-<FI 



-<br 



<Clk 



< Clr 



A simple 8-bit CPU: version "A' 



387 



Inside the code that describes the microcode word fields, the following fields are 
added, except fl_ar that already appeared in previous version. The new fields are 
used specifically to manage the FL register: 



field 


f l_ar [24] ; 


// FL 


< — ALU 


field 


f l_br [25] ; 


// FL 


< — bus 


field 


f l_bw[26] ; 


// FL 


— > bus 



Inside the opcode list there are new instructions and the same is for the microcode 
description: 



op move_mdr_fl { 

m^iT^ m r*)\T mH r "F 1 

ILLCLkJ 1 L L V ' V 1I.LLJ.J_ J L 

+0 [7 : 0] = 9; 


Q • 

-> r 


/ / mnvp MDR i~ n TPT. 

/ / V G? X J. J_/ -TV L* w C JLi 


operands op_0; 

}; 






op move_fl_mdr { 

m ^ t~i m o \ 7" ^ "F 1 mH r 

ILLCL \~J 1 L L v ' V J__L 1LLLJ.__ 

+0 [7 : 0] = 10; 




/ / mn\rc* TPT. i~n MDR 


operands op_0; 

}; 






op rotcl { 

m ^ t~i rnf r 1 • AO • 

1 L LCL kJ 1 U L L/l • ± f 

+0 [7 : 0] =42; 




// 7\ — 7\ T*ni~*i^& r*^ t*y*\7 7 ^ 


r-\ y~\ o -y -3 v~i fN o r~\ y~\ fl • 

(jpt; -L dllU.o OjJ U /■ 

}; 






op rotcr { 

map rotcr : 43; 
+0 [7 : 0] = 43; 




// A = A rotate carry right 


operands op_0; 

}; 






op add_carry { 
map add_carry : 
+0 [7 : 0] =44; 


44; 


// A = A + B + carry 


operands op_0; 







388 



A simple 8-bit CPU: version "A' 



op sub_borrow { 






map sub_borrow : 


45; 


// A = A - B - borrow 


+0 [7 : 0] = 45; 






operands op_0; 

}; 







// FL < — MDR 
// CNT < — 0 



// MDR < — FL 
// CNT < — 0 



begin microcode @ 0 
// 

move_mdr_f 1 : 

fl_br mdr_bw; 
ctrl_start ctrl_load; 

// 

move_f l_mdr : 

mdr_br fl_bw; 

ctrl_start ctrl_load; 
// 

rotcl : 

a_br alu_f =rotate_carry_lef t alu_bw fl_ar; // A < — A rot. carry 1 
ctrl_start ctrl_load; // CNT < — 0 

// 

rot cr : 

a_br alu_f =rotate_carry_right alu_bw fl_ar; // A < — A rot. carry r 
ctrl_start ctrl_load; // CNT < — 0 

// 

add_carry : 

a_br alu_f =a_plus_b_carry alu_bw fl_ar; // A < — A + B + carry 
ctrl_start ctrl_load; // CNT < — 0 

// 

sub_borrow : 

a_br alu_f =a_minus_b_borrow alu_bw fl_ar; // A < — A — B — borrow 
ctrl_start ctrl_load; // CNT < — 0 



end 



A simple 8-bit CPU: version "A' 



389 



Figure 8.102. Match between the contents of the memory that represents the mi- 
crocode (the couple of memory banks ml and m2 inside the control unit) and the 
microcode description itself. 



; <}/ «;:./ $«./' 



■ - % 



i i r f r / / 



\\\\ if t / 



movejndr _JJ: 



move Jljndr: _o 



■ V v 

0=not A 
1 =A and B 
2=A or B 
3=A xor B 
4=A « 1 
5=A » 1 
6=A « 1 arith 
7=A » 1 arith 
8=A rot left 
9=A rot right 
A=A rot carry left 
B=A rot carry right 
C=A plus B carry 
D=A minus B borrow 
E=A plus B 
F=A minus B 



?4% 

■2- 



b35 


M4 


b33 


b32 


b3I 


b30 


b29 


h28 


b27 


h2b 


h25 


b24 


b23 


b22 


b21 


b20 


bis 


blS 


bl7 


bid 


bis 


b!4 


bl3 


bl2 


bll 


blO 


b9 


bS 


b7 


bo 


b5 


b4 


b3 


b2 


bl 


bl.) 




I 






I 




a 






0 


1 




1 




0 


0 




0 






0 






0 




1 


0 




D 


1 




0 






0 






I 




0 


0 




0 






0 






1 




0 


0 




0 






0 






1 




0 


0 




0 


1 




0 






1 


1 














0 


i 


0 




1 














a 


. 


















1 


a 


1 




















( 


0 






0 






















D 


















:.) 




0 












1 


1 



rotcl: 








1 






a 










l 


l 


l 


0 


l 


0 


a 


l 
















a 




a 


a 




a 






















: 






□ 










□ 






: 










□ 


□ 




□ 
















a 


:; 


l 


l 



voter: 






0 






a 


c 


0 






a 


l 


l 


l 


0 


1 


1 


c 


1 


















a 


c 


C 


a 




















0 


1 




D 






0 




■ 


0 




( 


( 




0 






1 






1 




1 


0 




D 


0 




0 






l 


l 



add_carry: 








i 


a 




a 










1 


1 


1 


1 


0 


0 


a 


l 
















a 




a 


a 




a 
















0 






0 


c 


0 






0 




1 








a 


c 




















0 


c 


c 


0 


!. 






1 


1 



subjborrow: 












0 


1 


0 






a 


1 


1 


1 


1 


0 


1 


1 


1 


















0 


1 


1 


a 


1 




















a 




a 












a 










a 


















a 




a 


a 










1 


1 




b35 


M4 


b33 


b32 


b31 


b30 


b29 


b28 


b27 


b26 


b25 


b24 


b23 


b22 


bZl 


b20 


b!9 


blS 


bl7 


hi (j 


b!5 


bl4 


bl3 


bl2 


bll 


bill 




bti 


b7 


hd 


b5 


b4 


b3 


b2 


bl 


b(.) 



Table 8.103. Macroinstructions added for this version of the simple CPU. 



Syntax 


Description 


move_mdr_f 1 


It copies the MDR content into the FL register. 


move_f l_mdr 


It copies the FL content into the MDR register. 



390 A simple 8-bit CPU: version "A' 



Syntax 


Description 


rot cl 


It does a binary left rotation of the A register, using 
also the carrv flasr the Drevious carrv shifts in on the 

W 1 L.J 1.11V V 1>U 1 J llU^i 1.11V |_/1 T IV WU VV*1 1 J kJl 1.1 1 VkJ 1X1 Vll tllv 

right and the most significant bit is shifted out to the 
new carry value. 


rot cr 


It does a binary right rotation of the A register, using 
also the carrv flaff" the Drevious carrv shifts in on the 

w i l.j liiv vuii y iiti^i uiv i_/i V' t iv wu vv*ii y uiuxi>ij 111 vii tiiv 

left and the least significant bit is shifted out to the 
new carry value. 


add_carry 


It adds A and B and the previous carry, updating the 
A register and the new carry status. 


sub_borrow 


It subtracts A and B and the Drevious borrow uDdat- 

A V L." " — ' VI V*%^ V L.J J. M. iill\l LillVl VllV P"^ ' V_ y V-~* L.J i — ' 1 1 T » » V* I.-* Vl^iL 

ing the A register and the new borrow status (carry 
and borrow are the same flag). 



The following sections offer various examples, where the use of all the new instruc- 
tions is shown. 

8.5.1 Instruction "rotcl" and "rotcr" 

Listing 8.104. Macrocode example to experiment the rotation with carry: a value 
is loaded from the memory to the A register and a left rotation with carry is 
done five times, updating the value of A. Then the result is copied into B, before 
another value is loaded and rotated five times right. The complete source file 
should be available at attachments/xcpu/xcpu-a5-rotc.gm . 

begin macrocode @ 0 
start : 

load_ref #data_l 

move_mdr_a 

rotcl 

rotcl 

rotcl 

rotcl 

rotcl 

move_a_mdr 
move mdr b 



A simple 8-bit CPU: version "A' 



391 





rot cr 




rot cr 




rot cr 




rot cr 




rot cr 


s t op '. 






stop 


data 1 : 






.byte 160 


end 





Figure 8.105. RAM memory content: the memory cells marked with "xx" have 
an unknown and unspecified value. 

load_ref 

#data_l 

move_mdr_a 

rotcl 

move_a_mdr 
" move mdr b 




start: 
data 1: 



10 



F0 



01 


10 


05 


2A 


2A 


2A 


2A 


2A 


06 


07 


2B 


2B 


2B 


2B 


2B 


FF 


AO 

































OF 
IF 

FF 



0 1 



8 9 A B C D E 



392 



A simple 8-bit CPU: version "A' 



Figure 8.106. Data bus after the execution of the above example. Video: ogv 
http://www.youtube.com/watch ?v=Z13d-Tg5Cl Q 




8.5.2 Instruction "add_carry" 

Listing 8.107. Macrocode example to experiment the addition with carry: two 
16-bit numbers should be added, splitting them and adding in two steps. The 
numbers are 12FFi 6 and 1 lEE i6 . First there is the sum of FFi 6 and EEi 6 , without 
considering the previous carry, then there is the sum of 12i 6 and 1 1 i6 with the 
previous carry. The result is EDi 6 plus a carry the first time, where the second 
time the result is 24i 6 . Every partial addition is saved in memory, so that at the 
address matching the label data_4 a 16-bit result, little-endian, can be read. The 
complete source file should be available at attachments/xcpu/xcpu-a5-addc.gm . 

begin macrocode @ 0 
start : 

load_ref #data_0 

move_mdr_a 

load_ref #data_2 

move_mdr_b 

add 



A simple 8-bit CPU: version "A' 



393 





move a mdr 




ofn-rp rpf Ji H :=) -h a 4 

k_J L_- \-J J— \ - _L_ \ - _1_ 7T U i-A. a. 




10r5d fPf #dr5"t"rJ 1 

-1— \~S Ul. VwAi -1— V -1— 1 1 VwAi * ^- I . » <l- _1_ 




move mdr a 




load_ref #data_3 




movp mdr h 

ILL V^* V \ r* ILL J 




add_carry 




move_a_mdr 




store ref #data 5 


stop : 






stop 


// 0x1 2FF =4863 


data_0 : 






.byte OxFF 


data_l : 






•byte 0x12 


// 0x1 1EE = 4590 


data_2 : 






.byte OxEE 


data_3 : 






•byte 0x11 


data_4 : 






.byte 0 


data_5 : 






.byte 0 


end 





394 



A simple 8-bit CPU: version "A" 



Figure 8.108. RAM memory content before the program execution: the memory 
cells marked with "xx" have an unknown and unspecified value. 

- load_ref 

r- #data_0 

*- mo ve_mdr_a 

load_ref 
#data_2 

move_mdr_b 

add 

move_a_mdr 

store_ref 

#data_4 

load_ref 
► #data_l 




data_0: 
data_l: 
data_2: 
data_3: 
data_4: 

data 5: 



- stop 

#data_5 

^ store_ref 
^ move_a_mdr 

add_carry 



mo ve_mdr_a - 
load_ref 
#data_3 
move mdr b 



A simple 8-bit CPU: version "A" 395 
Figure 8.109. At the end of the macroprogram, the result is stored in memory. 





0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


c 


D 


E 


F 


00 


01 


15 


05 


01 


17 


07 


2E 


06 


03 


19 


01 


16 


05 


01 


18 


07 


10 


2C 


06 


03 


1A 


FF 


FF 


12 


EE 


11 

> 


ED 

• » 


24 

* 













OF 
IF 



data_4: 
data_5: 

Figure 8.110. Data bus after the execution of the above example. Video: ogv 
http://www.youtube.com/watch?v=lXu4MxWBwW4 



iniiiiiii j£ 



BGH3 



oscillator 

li ii ml 



-o-r-D 



D 



E.lnp 



-D 



«-r» 



br data buz 
cl* IR clc 



1 c 



br Addr bw 
RAH 



clc clip^ 

b'.V d 3 t H b 



5-H» 



□21 



I ili 



■D 



br data bw 



D 



bv data br 



r» 



Him 



" — T"D 



br data bw 
Ik MDR clc 



— D 



D 



-D 



in 



:lr " ell 
bw data br 



Oiii 



L .:ijn i 



3 



396 



A simple 8-bit CPU: version "A' 



8.5.3 Instruction "sub_borrow" 

Listing 8.111. Macrocode example to experiment the subtraction with bor- 
row: the subtraction 12EEi 6 -llFFi 6 is to be calculated. First a normal subtrac- 
tion EEi 6 -FFi6 is done, saving the request of borrow for the next subtraction: 
12i 6 — 1 1 ^-borrow . The first subtraction gives EF 16 with a borrow request; the 
second subtraction gives 00i 6 . Every partial subtraction is saved in memory, so 
that at the address matching the label data_4 a 16-bit result, little-endian, can 
be read. The complete source file should be available at attachments/xcpu/xcpu- 
a5-subb.gm . 

begin macrocode @ 0 
start : 

load_ref #data_0 

move_mdr_a 

load_ref #data_2 

move_mdr_b 

sub 

move_a_mdr 
store_ref #data_4 
load_ref #data_l 
move_mdr_a 
load_ref #data_3 
move_mdr_b 
sub_borrow 
move_a_mdr 
store_ref #data_5 

stop : 

stop 

// 0xl2EE = 4846 

data_0 : 

.byte OxEE 

data_l : 

.byte 0x12 
// 0x1 IFF =4607 

data 2 : 



A simple 8-bit CPU: version "A' 



397 





. byt e 


OxFF 










. byte 


0x11 


Haf a 4 * 








. byte 


0 


data 5 : 








. byte 


0 


end 







398 



A simple 8-bit CPU: version "A" 



Figure 8.112. RAM memory content before the program execution: the memory 
cells marked with "xx" have an unknown and unspecified value. 

load_ref 

r- #data_0 

*- mo ve_mdr_a 

load_ref 
#data_2 

move_mdr_b 

sub 

move_a_mdr 

- store ref 



stop: 



start: 



data_0: 
data_l: 
data_2: 
data_3: 
data_4: 

data 5: 



#data_4 
load_ref 
► #data_l 




^ store_ref 
^ move_a_mdr 

sub borrow 



_mdr_a - 

load_ref 
#data_3 
move mdr b 



A simple 8-bit CPU: version "A" 

Figure 8.1 13. At the end of the macroprogram, the result is stored in memory. 



399 





0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


c 


D 


E 


F 


00 


01 


15 


05 


01 


17 


07 


2F 


06 


03 


19 


01 


16 


05 


01 


18 


07 


10 


2D 


06 


03 


1A 


FF 


FF 


12 


EE 


11 

> 


EF 

• » 


00 













OF 
IF 



data_4: 
data_5: 

Figure 8.114. Data bus after the execution of the above example. Video: ogv 
http://www.youtube. com/watch ?v=ofPUzdIids8 




Si 



00H 0 



0000 



8.6 Version 7\6": branching 

In the sixth version of the simple CPU a new module is added, with the purpose to test 
conditions on the value of the status flags (the FL register). The condition evaluation 
results in the choice from the value of two registers: MDR if the condition is true, or 
PC otherwise. 



400 



A simple 8-bit CPU: version "A' 



Figure 8.115. Simple CPU version "A6". 




^ak CTRL c " 



Ck IR Or 



br Addr bw 



bw data br 



br data bw 



Clk MAR Qr 



Clr ° Clk 
bw data br 



— 2£ 



br data bw 



Clk MDR Or 



I ,1+8 |T" 



-[^ £ 



br data bw 



bw data br 



The SEL module gets two values from input A and input B . From the input Fi it gets 
the flags status, as it is output from the FL register. From the input / the module 
SEL receives the condition to be checked: if the condition is true and the input bw 
is asserted, the module writes to the bus the same value obtained from the A input, 
otherwise, if the condition results false, the module writes to the bus the same value 
obtained from the B input. 



A simple 8-bit CPU: version "A' 



401 



Figure 8.116. Module SEL, internal structure. 



t 

v 





f 


= 0 


if carry 




'J 


= 1 


if not carry 




£ 

T 


= 2 


if zero 




f 


= 3 


if not zero 




f 


= 4 


if negative 




f 


= 5 


if not negative 




f 


= 6 


if overflow 




f 


= 7 


if not overflow 



Fi 

V 



A B 

V V 



bO = carry 
b1 = zero 
b2 = negative 
b3 = overflow 



/ 8 / i 



dec 



O t — OJ CO 



■tf lO CD M 



=D- 
=D- 



o 



D- 

O- 
D- 



V- 



_ <bw 



bus 



Inside the code that describes the microcode word fields, the following fields are 
added. The new fields are used specifically to manage the SEL module: 



field sel_f[7:5]={ 
if_carry=0 , 
if_not_carry=l , 
if_zero=2 , 
if_not_zero=3 , 
if_negat ive=4 , 
if_not_negat ive=5 , 
if_overf low=6 , 
if not overflow=7 



}; 

field sel_bw[8]; 



// SEL — > bus 



402 A simple 8-bit CPU: version "A" 

Inside the opcode list there are new instructions and the same is for the microcode 
description: 



op jump_if_carry { 

map jump_if_carry : 16; 
+0 [7 : 0] =16; 


// 


jump 


to 


#nn 


if carry==l 


operands op_l; 

}; 












op jump_if_not_carry { 

map jump_if_not_carry : 17; 
+0 [7 : 0] =17; 


// 


jump 


to 


#nn 


if carry==0 


operands op_l; 

}; 












op ]ump_if_zero { 

map jump_if_zero : 18; 
+0 [7 : 0] =18; 


// 


jump 


to 


#nn 


if zero==l 


operands op 1; 

}; 












op ]ump_if_not_zero { 

map jump_if_not_zero : 19; 
+0 [7 : 0] =19; 


// 


jump 


to 


#nn 


if zero==0 


operands op 1; 

}; 












■ r- i r 

op ]ump_if_negative { 

map jump_if_negat ive : 20; 
+0 [7 : 0] =2 0; 


// 


jump 


to 


#nn 


if negative==l 


operands op 1; 

}; 












op 3ump_if_not_negat ive { 

map jump_if_not_negat ive : 21; 
+0 [7 : 0] =21; 


// 


jump 


to 


#nn 


if negative==0 


operands op_l; 

}; 












op jump_if_overf low { 

map jump_if_overf low : 22; 
+0 [7 : 0] =22; 


// 


jump 


to 


#nn 


if overflow==l 


operands op_l; 













A simple 8-bit CPU: version "A' 



403 



J ' 

on nnmT) i f nnf nvprf 1 ow i 

V 1 K_/ j ILL f— ' _L_ _L_ 1 1 V 1 \ . V 1 V \ - _L_ _L_ _L_ V 1 vv j 








map jump_if_not_overf low 


: 2 3; 


// 


jump to #nn if overflow==0 


+ 0 r 7 • 0 1 —? ? • 








operands op 1; 

}; 










begin microcode @ 0 








jump_if_carry : 








mar_br pc_bw; 




// 


MAR < — PC 


pc_Inc; 




// 


PC++ 


mdr_br ram_bw; 




// 


MDR < — RAM [mar] 


pc_br sel_f =i f_carry sel_bw 




// 


PC = (carry ? MAR : PC) 


ctrl_start ctrl_load; 




// 


CNT < — 0 


// 








jump_if_not_carry : 








mar_br pc_bw; 




// 


MAR < — PC 


pc_Inc; 




// 


PC++ 


mdr_br ram_bw; 




// 


MDR < — RAM [mar] 


pc_br sel_f =i f_not_carry sel_ 


_bw 


// 


PC = (not_carry ? MAR : PC) 


ctrl_start ctrl_load; 




// 


CNT < — 0 


// 








jump_if_zero : 








mar_br pc_bw; 




// 


MAR < — PC 


pc_Inc; 




// 


PC++ 


mdr_br ram_bw; 




// 


MDR < — RAM [mar] 


pc_br sel_f =i f_zero sel_bw 




// 


PC = (zero ? MAR : PC) 


ctrl_start ctrl_load; 




// 


CNT < — 0 


// 








jump_if_not_zero : 








mar_br pc_bw; 




// 


MAR < — PC 


pc_Inc; 




// 


PC++ 


mdr_br ram_bw; 




// 


MDR < — RAM [mar] 


pc_br sel_f =i f_not_carry sel_ 


_bw 


// 


PC = (not_zero ? MAR : PC) 


ctrl_start ctrl_load; 




// 


CNT < — 0 


// 








jump_if_negat ive : 








mar_br pc_bw; 




// 


MAR < — PC 


pc_Inc; 




// 


PC++ 



404 



A simple 8-bit CPU: version "A' 



mdr_br ram_bw; 






// 


MDR < — RAM [mar] 






pc_br sel_f=if_negative sel_ 


_bw 




// 


PC = (negative ? MAR 


: PC) 




ctrl_start ctrl_load; 






// 


CNT < — 0 






// 














jump_if_not_negat ive : 














mar_br pc_bw; 






// 


MAR < — PC 






pc_Inc; 






// 


PC++ 






mdr_br ram_bw; 






// 


MDR < — RAM [mar] 






pc_br sel_f=if_not_negative 


sel_ 


_bw 


// 


PC = (not_negative ? 


MAR : 


PC) 


ctrl_start ctrl_load; 






// 


CNT < — 0 






// 














j ump_i f _o ve r f 1 o w : 














mar_br pc_bw; 






// 


MAR < — PC 






pc_Inc; 






// 


PC++ 






mdr_br ram_bw; 






// 


MDR < — RAM [mar] 






pc_br sel_f =i f_overf low sel_ 


_bw 




// 


PC = (overflow ? MAR 


: PC) 




ctrl_start ctrl_load; 






// 


CNT < — 0 






// 














j ump_i f _no t_o ve r f 1 o w : 














mar_br pc_bw; 






// 


MAR < — PC 






pc_Inc; 






// 


PC++ 






mdr_br ram_bw; 






// 


MDR < — RAM [mar] 






pc_br sel_f=if_not_overf low 


sel_ 


_bw 


// 


PC = (not_overflow ? 


MAR : 


PC) 


ctrl_start ctrl_load; 






// 


CNT < — 0 






end 















A simple 8-bit CPU: version "A' 



405 



Figure 8.120. Match between the contents of the memory that represents the mi- 
crocode (the couple of memory banks ml and m2 inside the control unit) and the 
microcode description itself. 



' <?/ «V V 



% 1 



■Sj o s «y 



b35 b34 b33 b32 b31 b30 b29 b28 b27 b26 b25 b24 b23 b22 b21 b20 M9 b!8 b!7 b!6 b!5 b!4 b!3 M2 bll blO b9 



jumpjf_carry: 



r t ? / ' 

b7 b6 b5 b4 b3 b2 bl bO 



jumpJf_not_carry: 



jump_if_zero: 



jump_if_not_zero: 















































1 




















1 


















































c 


















c 


1 














□ 








a 




a 










a 




a 










a 


l 


:.: 








l 






a 




a 




a 




























































1 


0 


0 


0 






l 


























i 
















































l 


1 






a 








a 




:; 


a 








a 




a 










:: 




1 














i: 






1 


a 


























a 




a 


















0 


















0 


l 














□ 




































a 


1 


a 








l 








. 






a 












0 




c 














0 










c 




c 




c 




c 




c 


0 


1 


0 


0 


1 




0 


l 


c 




a 




a 








a 




a 


a 








. 




a 










a 




a 










a 








:: 


. 




l 


1 






a 




a 








: 














a 












. 


l 
















. 




1 


a 


. 








a 




a 




a 




: 


a 




a 








a 










a 




:; 














:: 




1 




a 






a 




a 




a 




a 




a 


a 








a 




a 










a 


1 


a 








1 


. 










. 


a 
















































: 








a 




l 


0 


1 


0 






l 




■ 


a 




a 




a 




a 




a 










a 




a 










a 




a 


















a 






l 


1 


































o 












l 








■ 












1 












:: 


























a 










a 




:; 


















l 




a 








c 




0 




c 










a 




c 










c 








1 




c 




c 


1 




D 




0 








c 








a 








a 




a 


a 




a 




a 




a 














a 










l 


0 


1 


1 


.; 




l 








3 


















■ 




a 
































■ 




0 




a 




1 


1 



b35 b34 b33 b32 Ml WO h29 b28 b27 b26 b25 b24 b23 b22 b21 h20 b]9 bis bl7 bl6 bl5 bl4 bl3 bl2 bll blO b9 



0=not A 
1 =A and B 
2=A or B 
3=A xor B 
4=A « 1 
5=A » 1 
6=A « 1 arith 
7=A » 1 arith 
8=A rot left 
9=A rot right 
A=A rot carry left 
B=A rot carry right 
C=A plus B carry 
D=A minus B borrow 
E=A plus B 
F=A minus B 



co i 



0= 


if carry 


1= 


if not carry 


2= 


if zero 


3= 


if not zero 


4= 


if negative 


5= 


if not negative 


6= 


if overflow 


7= 


if not overflow 



b7 b6 b5 b4 b3 b2 bl bO 



406 



A simple 8-bit CPU: version "A' 



jumpjfjnegative: 



jump_if_not_negative: 



jump_if_overflow: 



jump_if_not_overflow: 



■Q 



~4 & 

of «!•/ <V <V 



&jl i M -Q • .$ ; 

2 3 a/ 



.a 



o ; 



4, S^C# 



1 

b35 b34 b33 b32 b31 b30 b2 l ) b28 b27 b26 b25 b24 b23 b22 b21 b20 bl9 bl8 bl7 M6 MS bl4 bl3 bl2 bll blO b9 b8 b7 b6 b5 b4 b3 b2 bl bO 



t t r />" 



0 










; 


1 


0 


a 


a 


a 








i 


a 










1 


a 


l 


a 


a 
















l 




I 


I 












! 


1 


a 














c 


0 










( 


a 








a 




. 








1 
















■ 




0 


0 
















0 








■ 


3 


0 


l 










l 


c 


:: 








■ 


■ 












• 




3 


a 














■ 


3 






• 


• 


I 


a 












a 


1 


l 


0 


0 




• 


l 












■ 




3 


a 














• 


3 






• 


• 


I 


a 
















a 








• 


• 


l 


l 


















□ 




□ 










: 












:: 


l 


□ 














□ 




l 




. 














. 




a 
















:.: 










. 














. 








1 




















( 


c 


0 














c 












i 


1 








a 


l 


1 
























• 




3 


a 














• 


3 






• 


• 




• 














1 


l 


0 


1 




• 


l 












• 


■ 


3 


• 
















• 






• 


• 




• 












a 


a 


a 








• 


• 


l 


l 


□ 




□ 














□ 












:: 


□ 










:; 


l 




□ 


:: 












□ 


l 


















! 


! 


c 














1 












i 


:: 




















1 




















i 


I 


a 














1 


a 










i 


l 








a 


l 


t 




























! 


C 


a 














c 












! 


a 








a 


c 


l 


l 


l 


0 






l 












■ 




0 


0 
















0 






■ 


■ 


3 


0 














0 














l 


l 
















:; 






□ 










: 














l 


□ 














: 




l 










□ 


a 












□ 




□ 










0 












:; 




□ 














: 


l 




















! 


I 


(.: 














I 


0 










! 


l 










i 






























1 


I 


a 














1 


a 










1 


' 












l 


l 


l 


1 






l 












■ 




0 


0 














3 


0 






■ 


■ 


) 


0 


















3 










l 


l 



b35 b34 b33 b32 h3 1 b30 b2'> b28 b27 b26 b25 b24 b>3 b22 b2l h20 bIM bl 8 b]7 bl6 bl5 bl4 bl3 bl2 bll blO b9 



4 "-• 



4 / 



"\4 



0=not A 
1 =A and B 
2=A or B 
3=A xor B 
4=A « 1 
5=A » 1 
6=A « 1 arith 
7=A » 1 arith 
8=A rot left 
9=A rot right 
A=A rot carry left 
B=A rot carry right 
C=A plus B carry 
D=A minus B borrow 
E=A plus B 
F=A minus B 



-Q; 

0} / 



0= 


if carry 


1 = 


if not carry 


2= 


if zero 


3= 


if not zero 


4= 


if negative 


5= 


if not negative 


6= 


if overflow 


7= 


if not overflow 



b7 b6 b5 b4 b3 b2 bl bO 



Table 8.121. Macroinstructions added for this version of the simple CPU. 



Syntax 


Description 


jump_if_carry #ref 


If the carry flag is true, it jumps to the 
specified address. 


jump_if_not_carry #ref 


If the carry flag is false, it jumps to the 
specified address. 


jump_if_zero #ref 


If the zero flag is true, it jumps to the spec- 
ified address. 


jump_if_not_zero #ref 


If the zero flag is false, it jumps to the 
specified address. 



A simple 8-bit CPU: version "A' 



407 



Syntax 


Description 


jump_if_negat ive #ref 


If the negative flag is true, it jumps to the 
specified address. 


jump_if_not_negat ive %ref 


If the negative flag is false, it jumps to the 
specified address. 


jump_if_over f low %ref 


If the overflow flag is true, it jumps to the 
specified address. 


jump_if_not_overf low #ref 


If the overflow flag is false, it jumps to the 
specified address. 



Listing 8.122. Macrocode example to experiment the selection module: there is 
a cycle there a variable is incremented until it contains the result of a sum with 
another variable. The complete source file should be available at attachments/ 
xcpu/xcpu-a6.gm . 





Tin in /~i /~\ /~i /~\ /"n /~\ fn f l 


s t airt 






lOda rer ffconsiid.nii zero 




move mclr b 




1 r~\ ^ y~ "F itT7^"K — I ^ lr\ 1 p v" 
lUa la J_ i_ tr v d J L dU _L .A. 




move_mdr_a 




add 


cycle 






jump_if_zero #stop 




load_ref #variable_y 




move_mdr_a 




load_ref #constant_one 




move_mdr_b 




add 




move_a_mdr 




store_ref #variable_y 




load_ref #variable_x 




move_mdr_a 




load_ref #constant_one 




move_mdr_b 




sub 



408 



A simple 8-bit CPU: version "A' 



move_a_mdr 

store_ref #variable_x 
jump #cycle 

stop : 

stop 
const ant_zero : 

.byte 0 
constant_one : 

.byte 1 
variable_x : 

.byte 3 
variable_y : 

.byte 7 

end 



Figure 8.123. RAM memory content before the program execution: the memory 
cells marked with "xx" have an unknown and unspecified value. At the end of 
the execution, the memory cell at the address 23 i6 represents variable _y and it 
contains the value 0Ai 6 (10i 0 ). 



load_ref #constant_zero 
move_mdr_b 

load_ref #variable_x 
move_mdr_a 
add 

jump_if_zero #stop 

- load_ref #variable__y 




move_mdr_a 

load_ref #constant_one 

move_mdr_b 
- add 



A simple 8-bit CPU: 



version "A' 



409 



move_a_mdr 

store_ref #variable_y 

load_ref #variable_x 

-move mdr a 



load_ref #constant_one 
move_mdr_b 

r*~ sub 

move_a_mdr 

store_ref #variable_x 

jump #ciclo 

- jump stop 



constant _zero: 
constant_one: 

variable jc: 

variable_y: 
stop: 




410 



A simple 8-bit CPU: version "A' 



Figure 8.124. Data bus after the execution of the above example. Video: ogv 
http://www.youtube. com/watch ?v=hFoOoGf86tO 




10 le 



8.7 Version 7\7": stack 

In the seventh version of the simple CPU the SP register is added (stack pointer). 
This new register is to be used as the pointer for the stack. The stack is used mainly 
to allow the call of subroutines, with instructions like call and return, and to save 
and restore the registers. 



A simple 8-bit CPU: version "A" 



411 



Figure 8.125. Simple CPU version "A7". 




The SP register has two extra control inputs: Inc and Dec, which requires, respec- 
tively, the increment or decrement of the register content. 



412 



A simple 8-bit CPU: version 




A simple 8-bit CPU: version "A' 



413 



Inside the code that describes the microcode word fields, the following fields are 
added. The new fields are used specifically to manage the SP register: 



field 


sp_br [ 31 ] ; 


// SP < — bus 


field 


sp_bw [ 32 ] ; 


// SP — > bus 


field 


sp_Inc [ 33 ] ; 


// SP++ 


field 


sp_Dec [34] ; 


// SP— 



Inside the opcode list there are new instructions and the same is for the microcode 
description: 



op call_ref { 
map call_ref : 
+0 [7 : 0] =2 4; 


24; 


// call #nn 


operands op 1; 

}; 






op call_reg { 
map call_reg : 
+0 [7 : 0] =2 5; 


25; 


// call I 


operands op_0; 

1. 






j r 

op return { 

map return : 2 6; 
+0 [7 : 0] =26; 


// return 


operands op 0; 

}; 






op push_mdr { 
map push_mdr : 
+0 [7 : 0] =2 7; 


27; 


// push MDR 


operands op 0; 

}; 






op push_a { 

map push_a : 21 
+0 [7 : 0] =2 8; 


3; 


// push A 


operands op 0; 

}; 






op push_b { 







414 



A simple 8-bit CPU: version "A' 



map push_b : 2 9; 
+0 [7 : 0] =29; 
operands op 0; 

}; 


// push B 


op push_fl { 

map push_fl : 30; 
+0 [7 : 0] =30; 
operands op_0; 

}; 


// push FL 


op push_i { 

map push_i : 31; 
+0 [7 : 0] =31; 
operands op_0; 

}; 


// push I 


op pop_mdr { 

map pop_mdr : 48; 
+0 [7 : 0] =4 8; 
operands op_0; 

h 


// pop MDR 


op pop_a { 

map pop_a : 4 9; 
+0 [7 : 0] =49; 
operands op 0; 

}; 


// pop A 


op pop_b { 

map pop_b : 50; 
+0 [7 : 0] =50; 
operands op 0; 

}; 


// pop B 


op pop_fl { 

map pop_fl : 51; 
+0 [7 : 0] =51; 
ODPrands od 0: 

}; 


// pop FL 


op pop_i { 





A simple 8-bit CPU: version "A' 



415 



map pop_i : 52; 


// pop I 


+ 0 r 7 • 0 1 =52 • 




operands op 0; 

}; 





begin microcode @ 0 








call_ref : 








mar_br pc_bw; 




// 


MflJ? < — PC 


pc_Inc; 




// 


PC++ 


mdr_br ram_bw; 




// 


WDJ? < — RAM [mar] 


sp_Dec; 




// 


SC — 


mar_br sp_bw; 




// 


MAP < — SP 


ram_br pc_bw; 




// 


RAM [mar] < — PC 


pc_br mdr_bw; 




// 


PC < — MDP 


ctrl_start ctrl_ 


_load; 


// 


cwr < — 0 


// 








call_reg : 








sp_Dec; 




// 


SP — 


mar_br sp_bw; 




// 


MAP < — SP 


ram_br pc_bw; 




// 


RAM [mar] < — PC 


pc_br i_bw; 




// 


PC < — I 


ctrl_start ctrl_ 


_load; 


// 


CNT < — 0 


// 








return : 








mar_br sp_bw; 




// 


MAR < — SP 


sp_Inc; 




// 


SP++; 


pc_br ram_bw; 




// 


PC < — RAM [mar] 


ctrl_start ctrl_ 


_load; 


// 


CNT < — 0 


// 








push_mdr : 








sp_Dec; 




// 


SP — 


mar_br sp_bw; 




// 


MAP < — SP 


ram_br mdr_bw; 




// 


RAM [mar] < — MDP 


ctrl_start ctrl_ 


_load; 


// 


CNT < — 0 


// 








push_a : 








sp_Dec; 




// 


SP — 


mar_br sp_bw; 




// 


MAP < — SP 


ram_br a_bw; 




// 


RAM [mar] < — A 



416 



A simple 8-bit CPU: version "A' 



ctrl_start ctrl_ 


_load; 


// 


cwr < — o 


// 








push_b : 








sp_Dec; 




// 


SP — 


mar_br sp_bw; 




// 


MflJ? < — SP 


ram_br b_bw; 




// 


RAM [mar] < — B 


ctrl_start ctrl_ 


_load; 


// 


cwr < — o 


// 








push_f 1 : 








sp_Dec; 




// 


SP — 


mar_br sp_bw; 




// 


MAP < — SP 


ram_br fl_bw; 




// 


RAM [mar] < — PL 


ctrl_start ctrl_ 


_load; 


// 


cwr < — 0 


// 








push_i : 








sp_Dec; 




// 


SP — 


mar_br sp_bw; 




// 


MAP < — SP 


ram_br i_bw; 




// 


RAM [mar] < — J 


ctrl_start ctrl_ 


_load; 


// 


cwr < — o 


// 








pop_mdr : 








mar_br sp_bw; 




// 


MAP < — SP 


sp_Inc; 




// 


SP++ 


mdr_br ram_bw; 




// 


MOP < — RAM [mar] 


ctrl_start ctrl_ 


_load; 


// 


CNT < — 0 


// 








pop_a : 








mar_br sp_bw; 




// 


MAR < — SP 


sp_Inc; 




// 


SP++ 


a_br ram_bw; 




// 


A < — RAM [mar] 


ctrl_start ctrl_ 


_load; 


// 


CNT < — 0 


// 








pop_b : 








mar_br sp_bw; 




// 


MAR < — SP 


sp_Inc; 




// 


SP++ 


b_br ram_bw; 




// 


B < — RAM [mar] 


ctrl_start ctrl_ 


_load; 


// 


CNT < — 0 


// 








pop_f 1 : 








mar_br sp_bw; 




// 


MAR < — SP 


sp_Inc; 




// 


SP++ 



A simple 8-bit CPU: version "A' 



417 





fl_br ram_bw; 




// FL < — RAM [mar] 




ctrl_start ctrl_ 


_load; 


// CNT < — 0 


// 








pop_ 


_i : 








mar_br sp_bw; 




// MAR < — SP 




sp_Inc; 




// SP++ 




i_br ram__bw; 




// I < — RAM [mar] 




ctrl_start ctrl_ 


_load; 


// CNT < — 0 


end 









418 A simple 8-bit CPU: version 

Figure 8.130. Match between the contents of the memory that represents the mi- 
crocode (the couple of memory banks ml and m2 inside the control unit) and the 
microcode description itself. 



call_reg: 



return: 



jj ■<$■/ 4 



-Q / 



o 

c ; 



b35 b34 b33 b32 b31 MO b29 b2s l>27 b2ft 10.' "2-1 b23 b22 b21 b20 b!9 b!8 b!7 b!6 b!5 b!4 b!3 b!2 bll blO b9 



b7 b6 b5 b4 b3 b2 bl bO 



push_mbr: _o 























: 




: 


: 






] 
















l 




: 






■ 




: 


1 




: 


: 


: 


. 




. 


. 




f 


f 




. 


: 




f 


( 












. 




. 


. 


. 




i 


i 




. 






1 


1 




: 


: 


: 


: 




: 


: 


0 


: 


: 




: 


: 




: 


: 






. 


0 








1 


: 


: 




: 


1 




: 






: 


: 




: 




J 


1 




] 


: 




: 


i 




: 


! 




: 


: 






J 






i 




: 


! 


: 




: 


: 




: 


■ 




: 


: 




! 




! 


! 




1 


: 




l 


! 




I 


! 




! 


l 






1 






! 




i 


! 


: 


l 


! 


I 




: 






l 


I 




! 


: 




: 




: 


) 




: 


1 




: 


: 




] 


: 






: 






] 




: 


1 


: 




.) 


: 




: 






: 


1 




J 




1 


: 




: 


: 




: 


1 




: 


: 




: 


: 






i 






] 




: 


: 


: 




1 


: 




: 


0 




: 


: 


1 


: 






. 




. 


. 




. 


. 




. 


. 




. 






0 








. 






. 


. 






. 




. 


( 






. 


0 


1 


1 






1 




( 


I 




: 


: 










: 














. 






























: 


: 




. 




1 


. 




! 


f 






. 




f 


f 












f 






. 




l 








. 






f 


i 




: 


. 




: 




: 


: 


. 


: 


i 






! 




: 


: 






J 






i 






l 




. 


J 


: 




! 






J 


l 




: 




f 


i 




; 


; 


1 


! 


! 




f 


I 




! 


I 






; 






l 




i 


f 






! 


I 




; 






! 


I 


l 


f 


I 


f 


I 




; 


; 




! 


1 




i 


I 




! 


I 












l 




i 


f 


f 




f 


f 




; 


0 




! 


I 




1 


1 


. 


. 




1 


. 




. 


. 




. 


. 




. 


. 












. 




. 


. 




l 








f 


0 




. 


. 




. 








l 


: 






J 


J 






: 




J 








: 






] 




] 




















J 


: 




J 




1 


f 










I 


f 






: 




( 


i 
















l 




i 




i 


i 










1 


I 


l 


: 




f 


! 










( 


! 




: 


. 




( 


i 
















. 




. 




! 


i 










f 


f 




1 


1 


J 


1 




J 


J 




i 


0 




! 


: 




J 


i 






! 






J 




! 


J 


! 




J 






J 






) 


) 




! 




J 


i 




l 


J 




i 


1 




: 


: 




i 








! 






] 




! 


! 


! 


l 


i 


i 




J 






1 


) 


• 


! 












0 


» 








0 


(* 




0 








0 


! 








0 


1 


0 


i 


l 




i 


0 






0 






0 


D 








f 


. 
























. 










. 


. 


. 










. 






. 






1 


1 



b35 b34 b33 b32 b31 b30 b29 b28 b27 b26 b25 b24 b23 b22 b21 b20 bl9 bl8 bl7 bl6 bl5 bl4 bl3 bl2 bll blO b9 



8? 



f t 


















C 




¥ 


s 







4/ 



0=not A 
1 =A and B 
2=A or B 
3=A xor B 
4=A « 1 
5=A » 1 
6=A « 1 arith 
7=A » 1 arith 
8=A rot left 
9=A rot right 
A=A rot carry left 
B=A rot carry right 
C=A plus B carry 
D=A minus B borrow 
E=A plus B 
F=A minus B 



\<S> 



03 



0= 


if carry 


1= 


if not carry 


2= 


if zero 


3= 


if not zero 


4= 


if negative 


5= 


if not negative 


6= 


if overflow 


1= 


if not overflow 



b7 b6 b5 b4 b3 b2 bl bO 



A simple 8-bit CPU: version "A' 



419 



»q' <5/ <&'' 



v.. 



3 \<£ "**// "i- ^/ sjV c; 



-o/ 



i 



Hi r M / / 



b35 b34 b33 b32 b31 b30 b29 b28 b27 b26 b25 b24 b23 b22 b21 b20 bl9 bl8 bl7 bl6 bl5 bl4 bl3 bl2 bll blO b9 



b7 b6 b5 b4 b3 b2 bl bO 



push_a: 



pushjb: 



push _fl: 



push_i: 





1 


D 


D 


0 


0 


0 


( 


( 




0 


0 


( 


0 


0 


0 


0 


0 


0 


0 


0 


0 


0 


( 




( 


0 


0 


0 


0 


EE 


0 


0 




0 




0 


0 


0 


1 


0 


0 


0 


! 


0 


i 


0 


0 


0 


(i 


0 


0 


0 


0 


0 


0 


0 


0 






1 


< 


0 


(j 


0 


0 


0 


EE 










0 


0 


!.) 


0 


0 


n 


0 






< 


0 


0 




(j 


0 


u 


0 


1 


!j 


n 




n 


1 


< 




< 


0 


0 


(1 


(1 


El 


EE 






n 




0 


: 


IS 


u 


0 


0 


n 






0 


0 


0 






: 


0 


0 


: 


!.! 


!) 


0 


0 


0 




0 


V 


0 


0 


(1 


(j 


: 


Ej 






1 


1 


EE 


1 


0 




: 


: 






::i 


:.) 


El 


:.) 


3 






0 


El 






: 


: 


j 


) 




3 


I) 


. 


El 




El 






J 




: 


: 


• 


E. 


;. 


1 










0 


• 


1 




0 




E 


;. 


• 


;. 


E 


[ 








0 


1 


i) 




1 


• 




E 








0 






c 




[ 


[ 


[ 


0 


1 


(.1 


0 


1 




(i 


• 


[ 






0 


[ 


[ 


[ 




1 




(.! 


0 


• 


• 






0 


[ 












[ 


[ 


0 








0 


0 


0 






c 




0 


S 




E 


[ 


[ 








0 


• 


• 


> 








! 


[ 






1 


1 


• 


1 




: 












• 


0 


• 




1 


! 






0 


! 






















i 


!.) 


; 










• 


§ 


<, 


l 










0 




1 


• 


0 




0 


E 




e 


E 










0 


1 


0 






• 


• 


E 


i 






' 






!. 




< 












1 










; 


E) 




0 


E 








1 




0 












!.) 


; 












G 


!.) 


G 


( 




( 
















G 


f.) 




!.) 


G 


i 




i 


. 
















E) 


0 


E 




1 


1 


0 


1 


0 




0 


0 


0 


! 




( 


0 


0 


I 


0 


0 


: 


0 


G 


0 


0 


0 


0 


0 


0 


( 


< 


0 


0 


0 


0 


0 


EE 










0 


0 


0 


l 


0 


0 


0 






< 


(1 


0 




() 


0 


0 


0 


0 


0 


0 


0 


0 


0 


0 


1 


< 


(i 


0 


(1 


0 


0 


EE 


















J 


1 


: 


■ 




:.) 


. 


:i 


3 


E 












J 


: 


! 


1 


E 


:.) 


EE 




El 


El 


. 






1 




: 




0 


0 


0 


0 


n 


0 


n 


0 


■ 


0 


0 


0 




0 


0 


0 


(i 


!.) 


G 


0 


0 


0 


n 


0 


0 


<) 








0 


EE 


!.) 


u 




1 


1 



b35 b34 b33 b32 b31 b30 b29 b28 b27 b26 b25 b24 b23 b22 b21 b20 bl9 bl8 bl7 bl6 bl5 bl4 bl3 bl2 bll blO b9 



4 i i \ 



■-o 



O=not A 
1=A and B 
2=A or B 
3=A xor B 
4=A « 1 
5=A » 1 
6=A « 1 arith 
7=A » 1 arith 
8=A rot left 
9=A rot right 
A=A rot carry left 
B=A rot carry right 
C=A plus B carry 
D=A minus B borrow 
E=A plus B 
F=A minus B 



09 .' 



0= 


if carry 


1= 


if not carry 


2= 


if zero 


3= 


if not zero 


4= 


if negative 


5= 


if not negative 


6= 


if overflow 


7= 


if not overflow 



b7 b6 b5 b4 b3 b2 bl bO 



420 



A simple 8-bit CPU: version "A' 



-q; 



•o. ^/ 



v., 

-Q : -J? • 



t . O : 



\ \ i i iff/ 



b35 


534 


b33 


b32 


Ml 


b30 


b29 


b28 


b27 


b26 


b25 


b24 


b23 


b22 


b21 


b20 


bl9 


bl8 


bl7 


bl6 


bl5 


bl4 


bl3 


bl2 


bll 


blO 


b9 


b8 


b7 


b6 


b? 


b4 


b3 


b2 


bl 


bl) 


popjndr: 


: 






1 




J 


:i 


J 






' 






3 


: 


J 




! 




J 


: 




J 




1 


J 


: 


J 






3 




J 


3 








: 




1 


) 




: 




J 






J 


3 




:.) 


) 


: 


J 


J 




J 


! 




J 






: 




J 


3 




3 




J 






;.) 




: 




!.) 


: 




: 




: 






: 




0 




: 


: 




. 




: 


: 


1 


: 




: 


: 


1 


: 




0 






i 










: 






: 




: 




: 






: 






0 


: 


: 






0 


: 


i 




J 






J 


:i 


: 






!) 




: 


3 


1 


i 



pop_a: 



popjl: 



b35 b34 b33 b32 b31 t>30 b29 b28 b27 b26 b25 b24 b23 b22 b21 b20 bl9 bl8 bl7 bl6 bl5 bl4 bl3 bl2 bll blO b9 



O 

off 















C 




si 





0=not A 
1=Aand B 
2=A or B 
3=A xor B 
4=A « 1 
5=A » 1 
6=A « 1 arith 
7=A » 1 arith 
8=A rot left 
9=A rot right 
A=A rot carry left 
B=A rot carry right 
C=A plus B carry 
D=A minus B borrow 
E=A plus B 
F=A minus B 



'-.■2- \ 



0= 


if carry 


1= 


if not carry 


2= 


if zero 


3= 


if not zero 


4= 


if negative 


5= 


if not negative 


6= 


if overflow 


7= 


if not overflow 



n 


0 


0 


1 


(i 


n 


0 


0 


0 


0 


0 


0 




0 


; 


n 


0 


0 


( 


0 


0 


0 


0 


0 


l 


0 


0 


0 


0 


0 


< 


0 


(1 


0 


(J 




i 




1 


: 




] 




: 






: 








: 


: 




: 


3 


: 


: 




1 






: 




J 






:.! 




1 






;.) 


: 


0 


0 


: 




: 




: 






: 




0 




: 


: 




: 


1 


: 


: 




; 




0 


: 


1 


: 




0 






: 








! 






J 




: 




: 






! 






3 


: 


J 




: 




: 


J 




J 






J 




: 






3 




J 




1 


i 



f 




0 


1 




1 




; 






1 








; 


. 




1 




1 


; 




1 




1 


1 




; 




0 






1 








: 




1 


: 




l 




: 






: 




0 




: 


: 




: 




i 


: 




I 




D 


; 




: 




0 






: 








! 


j 




: 




J 




J 


i 




: 






3 


J 


: 




J 


3 


J 


: 




: 






: 


1 


J 






3 




i 


3 






; 


(i 


0 


1 


(J 


n 


0 


n 


(j 


0 


0 








n 


0 


0 


0 


0 


n 


0 


(i 


0 


0 


0 


0 


0 




0 


!) 


( 


(i 


0 


0 


1 


1 



J 






1 




j 




: 






: 








J 


] 




J 


3 


J 


: 




] 




l 


: 




: 






3 




i 






0 


0 


0 


1 


n 


0 


0 


o 


0 


0 


0 


0 




u 


> 




0 


0 




C 


n 


0 


0 


n 


0 


0 


0 


0 


U 


0 


!.) 


( 


«! 


0 


0 


0 




! 










: 




: 






1 






3 


: 






: 


3 


: 


: 




j 






: 


i 








3 




J 






0 






0 












































0 










0 










1 


1 



: 






1 




: 




: 






: 






3 




i 




: 


3 


: 


: 




: 


3 


1 


: 




: 






3 




: 






;.) 


: 




1 


. 




; 




: 






: 




0 




i 


: 




: 




; 


: 




; 




0 


: 




: 




0 






: 








! 






! 




: 




: 






: 






3 


: 


: 




: 


3 


: 


1 




i 






: 


1 


: 






:.) 




J 








: 






: 




: 




: 






: 






:.! 


: 


: 




: 


:.) 


: 


: 










] 




: 










: 




l 


i 



b7 b6 b5 b4 b3 b2 bl bO 



A simple 8-bit CPU: version "A" 421 



Table 8.131. Macroinstructions added for this version of the simple CPU. 



Syntax 


Description 


call_ref %ref 


It decrements the value inside the SP register and 
save in memory, at the new SP position, the address 
of the next instruction (after call_ ...), then it updates 
the PC register with the address specified (the argu- 
ment). That is: it calls the procedure storing inside 
the stack the return address. 


call_reg 


It decrements the value inside the SP register and 
save in memory, at the new SP position, the address 
of the next instruction (after call_-), then it updates 
the PC register with the address contained inside /. 
That is: it calls the procedure storing inside the stack 
the return address. 


return 


It increments the SP register and it restore the regis- 
ter PC loading from memory the content at the ad- 
uress pomieu oy me upuaieu »3x . inai is. 11 returns 
from a procedure call. 


push_mdr 


It saves on top of the stack the value of MDR. 


push_a 


It saves on top of the stack the value of A . 


push_b 


It saves on top of the stack the value of B. 


push_f 1 


It saves on top of the stack the value of FL. 


push_i 


It saves on top of the stack the value of /. 


pop_mdr 


It dods from the stack a value that is loaded bv the 
MDR register. 


pop_a 


Tt nons from the stack a value that is loaded bv the A 
register. 


pop_b 


It pops from the stack a value that is loaded by the B 
register. 


pop_f 1 


It pops from the stack a value that is loaded by the 
FL register. 



422 



A simple 8-bit CPU: version "A' 



Syntax 


Description 


pop_i 


It pops from the stack a value that is loaded by the / 
register. 



8.7.1 Instruction "push" and "pop" 

Listing 8.132. Macrocode example to experiment the instruction for adding and 
removing values from the stack: it is saved a value from the A register and then 
it is restored inside the B register. The complete source file should be available 
at attachments/xcpu/xcpu-a7 -push-pop. gm . 



begin 


macrocode @ 0 


start 






load_ref #sp_bottom 




move_mdr_sp 




load_ref #data_0 




move_mdr_a 




push_a 




pop_b 


stop : 






stop 


sp_bottom : 




.byte 0x10 


data_ 


0 : 




.byte OxCC 


end 





A simple 8-bit CPU: version "A' 



423 



Figure 8.133. RAM memory content: the memory cells marked with "xx" have 
an unknown and unspecified value. The memory cell at the address 0F i6 is written 
by the instruction push_a. 



datajO: 

spjbottom: 
stop: 

start: 



load_ref #sp_bottom 
*- mo ve_mdr_sp 

load_ref #data_0 
move_mdr_a 
- push_a 





value saved 
inside the stack 




00 


01 


09 


OD 


01 


OA 


05 


1C 


32 


FF 


10 


cc 










CC 


10 












































FO 




































0 


l 


2 


3 


4 


5 


6 


7 


8 


9 


A 


B 


C 


D 


E 


F 



IF 



FF 



424 



A simple 8-bit CPU: version "A" 



Figure 8.134. Data bus after the execution of the above example. Video: ogv 
http://www.youtube. com/watch ?v=vAdVww31D7I 




« 



8.7.2 Instruction "call" and "return" 

Listing 8.135. Macrocode example to experiment the instructions for calling a 
procedure and returning from a procedure. The complete source file should be 
available at attachments/xcpu/xcpu-a7-call-return.gm . 



begin macrocode @ 0 
start : 

load_ref #sp_bottom 

move_mdr_sp 

call_ref #elab 

move_a_mdr 

move_mdr_b 

jump #stop 



elab 



load_ref #data_0 
move mdr a 



A simple 8-bit CPU: version "A' 



425 



load_ref #data_l 

move_mdr_b 

add 

return 

stop : 

stop 
sp_bottom : 

.byte 0x20 

data_0 : 

.byte OxOA 

data_l : 

.byte OxOB 

end 



426 



A simple 8-bit CPU: version "A' 



Figure 8.136. RAM memory content: the memory cells marked with "xx" have 
an unknown and unspecified value. The memory cell at the address lF i6 is written 
by the instruction call_ref . 

load_ref #sp_bottom 
move_mdr_sp 

call_ref #elab 
move_a_mdr 
move_mdr_b 
jump #stop 

load_ref #data_0 
move_mdr_a 

load_ref #data_l 

move_mdr_b 
- add 




oo 

10 



01 


12 


0D 


18 


09 


06 


07 


OF 


M 
ll 


01 


13 


05 


01 


14 


07 


2E 


1A 


FF 


20 


OA 


OB 






















05 



stop: 
spjbottom: 
data_0: 
data 1: 




OF 
IF 




A simple 8-bit CPU: version "A' 



427 



Figure 8.137. Data bus after the execution of the above example. Video: ogv 
http://www.youtube.com/watch?v=nWdXMvegkjc 




8.8 Version 7\8": I/O 

The previous version of the simple CPU is complete enough to show the main func- 
tions of a common CPU. This version extends the project introducing I/O devices. 
Two new busses are added, used for the data to move with devices and to select a 
specific device. 

8.8.1 Communication with asynchronous devices 

Usually, the I/O devices are not synchronous with the CPU clock, therefore it is nec- 
essary a protocol, so that it can be made a request of an action to the device and a 
feedback from the device can be received. The I/O devices used in this simple CPU 
project have externally the connections shown in the next figure. 



428 



A simple 8-bit CPU: version "A' 



Figure 8.138. One input device and one output device. 





REQ 

DATA keyboard 

ACK 
CLR 




REQ 

DATA ,. , 

display 

ACK 
CLR 


-► 


-► 


<- 


-► 


4- 


+■ 


-► 





The input or output DATA allows to move the information that is needed by the device 
or that is generated from it. The inputs REQ (request) and ACK (acknowledge) are 
used to negotiate the information movement (the input CLR is used only to clear the 
device). Two examples should be done, to examine the procedure of reading from the 
device and of writing on it. 

To communicate with an input device, from which a data is to be read, it is required 
to activate the input REQ (tj) to request the data. The device receives the request and 
prepares the output DATA with the information (t 2 ), then it activates the output ACK 
(t 3 ). At that point, finding the output ACK active, it is possible to read from the output 
DATA (t 4 ) and after the read operation it is possible to disable the input REQ (t 5 ). 
The device, finding the input REQ disabled, knows that the information was taken, 
then it stops to keep it (t 6 ) and disables the output ACK (t 7 ). 

Figure 8.139. Phases for reading an input device ad for writing to an output de- 
vice. 

read from the device write to the device 

t 0 tj t 2 t 3 1 4 t 5 t 6 t 7 t 0 tj t 2 t 3 t 4 t 5 t 6 t 7 



REQ 



ACK 



valid data 
< >■ 



valid data 
< > 



To communicate with an output device, where an information is to be written, it is 



A simple 8-bit CPU: version "A' 



429 



necessary to prepare that data to the input DATA {to), then it is necessary to activate 
the input REQ (tj) to tell the device that the data is ready. Then the device gets the 
information (t 2 ) and it confirms activating the output ACK (t 3 ). Finding the confirma- 
tion, it is not necessary to keep the information on the input DATA DATA (t 4 ) and the 
input REQ is disabled (f 5 ). The device, finding that the request is completed, disables 
the output ACK (t 7 ) concluding the operation. 

8.8.2 I/O devices implementation 

At the moment, only two I/O devices are implemented: a keyboard and a screen. As 
the project is developed with TKGate, the devices are made through TCL/Tk code. 
The code that is shown was obtained modifying similar devices from the TKGate 
library. 

Listing 8.140. File 'share/tkgate/vpd/kbd. tcl' to simulate the keyboard 
input. The program shows a little empty window, which should be selected to 
type something that could be received by the related virtual device. 

VPD :: register KBD 
VPD::allow KBD::post 

namespace eval KBD { 

# Public variables declaration. $kbd_w is an array that is 

# use only for the element $n. $kbd_w($n) identifies uniquely 

# the working interface instance. 

variable kbd_w 
variable KD 

# Function required by TKGate to create the interface . 

proc post {n} { 

variable kbd_w 

# It creates a window and saves the object inside the array 

# $kbd_w. 

set kbd_w($n) [ VPD : : createWindow "KBD $n" -shutdowncommand "KBD::unpost $n"] 

# It links the keyboard typing, related to the object represented 

# by $kbd_w ($n) , to the sendChar function. 

bind $kbd_w($n) <KeyPress> "KBD :: sendChar $n \"%A\"" 

# It opens a write channel, named "KD" . 

if {[info exists : : tkgate_islnitialized] } { 
VPD : : outsignal $n . KD KBD : : KD ( $n) 

} 

} 

# Function that gets the typing and puts it into the channel 

# "KD", related to the current interface instance. 

proc sendChar {n key} { 



430 



A simple 8-bit CPU: version "A' 





variable KD 






if { [string length $key ] 


== 1 } { 




binary scan $key c c 






set KBD : : KD ($n) $c 






} 






} 






# Function required by TKGate 


to destroy the interface. 




proc impost {n} { 






variable kbd_w 






destroy $kbd_w($n) 






unset kbd_w($n) 






} 




} 







Listing 8.141. File 'share/tkgate/vpd/scr . tcl' to simulate the output on 
a character screen. The program shows a window where the sent characters are 
shown. Inside the code there is reference to the file 'text cur s . b' that is already 
included with the TKGate distribution. 

image create bitmap txtcurs -file " $bd/txtcurs . b" 

VPD : : register SCR 
VPD::allow SCR: :post 
VPD : : allow SCR::data 



namespace eval SCR { 

# Public variables declaration: they are arrays where only 

# the element $n is used. The element $n identify uniquely 

# the working interface instance . 

variable scr_w 
variable scr_pos 

# Function required by TKGate to create the interface. 

proc post {n} { 

variable scr_w 
variable scr_pos 

# It creates the window and it saves the object inside the array 

# $scr_w. 

set scr_w($n) [ VPD : : createWindow "SCR $n" -shutdowncommand "SCR::unpost $n"] 

# For convenience, it copies the object reference inside the local variable 

# $W and then the object is referred only with that variable . 

set w $scr_w($n) 

text $w.txt -state disabled 

pack $w.txt 

# It puts the cursor at the end of the shown text . 

$w.txt image create end -image txtcurs 



A simple 8-bit CPU: version "A' 



431 



# It opens a reading channel, called "RD " and it connects it to the 

# function "data". 

if {[info exists : : tkgate_islnitialized] } { 

VPD : : insignal $n . RD -command "SCR::data $n" -format %d 

} 

# It clears the counter for the shown characters on screen. 

set scr_pos ($n) 0 

} 

# Function required by TKGate to destroy the interface . 

proc impost {n} { 
variable scr_w 
destroy $scr_w($n) 
unset scr_w($n) 

} 

# Function used for receiving the data to be shown on screen. 

proc data {n c} { 
variable scr_w 
variable scr_pos 

# For convenience, it copies the interface object reference inside 

# the local variable $w. 

set w $scr_w($n) 
catch { 

# The $c variable contains the character to be shown. 

if { $c == 7 } { 

# BEL 

bell 
return 

} elseif { $c == 127 | | $c == 8 } { 

# DEL I BS 

if { $scr_pos ($n) > 0 } { 

# It deletes the last shown character, but only if the 

# characters counter is greater then zero, otherwise 

# the cursor would disappear and the newly received 

# characters could be placed inside an invisible area 

# of the virtual screen. 
$w.txt configure -state normal 
$w.txt delete "end - 3 chars" 
$w.txt see end 

$w.txt configure -state disabled 

set scr_pos($n) [expr {$scr_pos ( $n) - l}] 

} 

return 
} elseif { $c == 13 } { 

# CR is translated into LF . 

set c 10 

} 



432 



A simple 8-bit CPU: version "A' 









# It converts the character number into a symbol that can 








# be shown. 








set x [format %c $c] 








# It shows the symbol . 








$w.txt configure -state normal 








$w.txt insert "end - 2 chars" $x 








$w.txt see end 








$w.txt configure -state disabled 








# It updates the shown characters counter. 


} 


} 


} 


set scr_pos($n) [expr {$scr_pos ($n) + 1}] 



The two TCL/Tk programs are called by some Verilog code. The following listings 
show the modules keyboard and display, which appear graphically as in the figure 
8.138. 

Listing 8.142. Verilog code for the keyboard module. 

module keyboard (DATA, REQ, ACK, CLR); 

output ACK; 

output [7:0] DATA; 

input REQ; 

input CLR; 

reg ready; 

reg [7:0] key; 

initial 
begin 

ready = 0; 
key = 0; 
end 

always 
begin 

@ (posedge CLR) 
ready = 0; 
key = 0; 



A simple 8-bit CPU: version "A' 



433 



end 

initial $tkg$post ( " KBD " , "%m") ; 

always 
begin 

@ (posedge REQ) ; 

# 5; 

key = $tkg$recv ( "%m. KD" ) ; 

# 5; 

ready = l'bl; 

# 5; 

@ (negedge REQ) ; 

# 5; 

ready = 1'bO; 
end 

assign DATA = key; 
assign ACK = ready; 

endmodule 



Listing 8.143. Verilog code for the display module. 

module display (DATA, REQ, ACK, CLR); 

output ACK; 

input [7:0] DATA; 

input REQ; 

input CLR; 

reg ready; 

initial 
begin 

ready = 0; 
end 



434 



A simple 8-bit CPU: version "A' 



initial $tkg$post ("SCR", "%m") ; 

always 
begin 

@ (posedge CLR) 

ready = 0; 
end 

always 
begin 

@ (posedge REQ) ; 

# 5; 

$tkg$send ( "%m.RD", DATA) ; 

# 5; 

ready = l'bl; 

# 5; 

@ (negedge REQ) ; 

# 5; 

ready = 1 ' bO ; 
end 

assign ACK = ready; 
endmodule 



Until now, the described devices can work only asynchronously, but to be used, they 
must be adapted to work synchronously with the CPU. 

8.8.3 External appearance of the synchronous interfaces 

The synchronous interfaces for the I/O devices should be connected to the CPU data 
bus, just like the other modules already implemented. However, to simplify the con- 
nections, instead of having personal control lines, an additional bus is created for the 
I/O module address to be selected. 



A simple 8-bit CPU: version "A" 



435 



Figure 8.144. I/O modules connection. 
I/O devices control bus 



I/O device address bus 




clock line 



clear line 



CPU data bus 



As the figure shows, the bus connected to the inputs ADDR is used to select the 
device, while the bus connected to the inputs CON is used to uniform the control 
lines for all the I/O modules. Please notice that the inputs CON are the same for all 
I/O modules, but every module uses only the lines that it requires, ignoring the others: 



CON 



0 



bus read 

bus write 
request 

is ack? 



The lines bus read and bus write are the same of the other modules already described 



436 



A simple 8-bit CPU: version "A' 



« 



and they refer to the request to read the CPU data bus or write to the CPU data bus. The 
line request is used to request a read or write operation on the device, but without the 
need to keep it active as it should for the asynchronous protocol already mentioned. 
The line is ack? is used to obtain, somehow, an acknowledgment from the device. 

8.8.4 Synchronous keyboard interface 

The keyboard interface module uses only two out of the four control lines: bus write 
and request. 

Figure 8.146. Module kbd, which connects the keyboard to the CPU data bus. 



— i 



CON 0 = bus read 
CON 1 = bus write 
CON 2 = request 
CON 3 = is ack? 




v- 



[$] 



Preset 

ik 

Cteaj 



Preset 

J 

Clk JK 

K 

Clear 



REQ 
DATA 
ACK 
CLR 



keyboard 



4- 


+ 




ADDR 


data 


CON 


Clk 


KBD 


Clr 




bus 







,'a 



a) request 

b) not operate 

c) bus write 

[£] When a "bus write" request is received, the saved ack is cleared. 

[$] The "request" is allowed only if there isn't waiting a previous saved ack. 



To communicate with the keyboard module it is necessary to start with a request sig- 
nal. Then, after a positive clock edge it is saved inside the upper JK flip-flop, which 
is activated. That flip-flop has the task to keep the request active on the input REQ 
of the device. The second central JK flip-flop has the task to save the acknowledge 
produced by the output ACK and, if that acknowledge is active inside the flip-flop, it 
does not allow to receive another request. After a request is correctly received and 
saved, if the device has a character ready to be output, it replies almost immediately, 
placing that character on its DATA output and activating the output ACK. At the sec- 
ond positive clock edge, the flip-flop responsible for the request signal is cleared and 
instead is activated the second flip-flop responsible for the acknowledge. However, 
the device continue to keep its DATA with the character to be read. Then, a bus write 
signal is received, allowing to write the character read from the device into the CPU 



A simple 8-bit CPU: version "A' 



437 



data bus. This action clears also the acknowledge flip-flop. If otherwise, the keyboard 
device is not yet ready to offer a character, the interface will write to the CPU data 
bus a null value (00i6), because the acknowledge flip-flop is not activated. 

At the macrocode level, if the keyboard read produces a null character, it just means 
that there is not a character ready and the keyboard read should be retried. 

8.8.5 Synchronous display interface 

The DSP module uses all the control lines, because it must be able to read from the 
CPU data bus when a character is to be shown on the screen, but must also be able to 
write to the bus to give the acknowledge of the work properly done. 

Figure 8.147. Module dsp. 



« 



CON> 

CON 0 = bus read 
CON 1 = bus write 
CON 2 = request 
CON 3 = is aok? 




The DSP module uses a register made out of eight D flip-flops (positive edge triggered, 
module DR8) which is used to save the character to be shown on the screen. However, 
when the control line is ack? is active, the DSP module writes to the CPU data bus 
the result of its work: 00i 6 means that the last character to be displayed is not already 
appeared, whereas FFi 6 means that the last character to be displayed was correctly 
shown. 



438 



A simple 8-bit CPU: version "A' 



Figure 8.148. Building DRn modules. 



« 



D 

V 



module «DR1> 



Q < 



module «DR2» 



module «DR4>; 



-<L 



~1* 



-<Ck 



Ck>- 



C > 



DR1 



DR1 



-<L 



0k>- 



C > 



72 



DR2 L 



DR2 L 



-<L 



A 
C 



To show a character on screen, it is necessary to start activating the control line 
bus read : after the next clock positive edge the internal data register loads the char- 
acter reading it from the CPU data bus, while the JK flip-flop at the middle is cleared 
and so is the ack multiplexer, connected to the flip-flop output. Then the control line 
request should be activated: after the next clock positive edge this value is saved in- 
side the JK flip-flop on the top side, activating the input REQ of the device. Then, 
after a while, the device shows the character that is already available at its DATA 
input (it comes from the data register) and then it replies activating its ACK output. 
When the ACK output from the device is active and a new clock positive edge comes, 
the JK flip-flop on the top is reset and the other JK flip-flop is activated, switching the 
connected multiplexer. 

To show a character, only two clock cycles are required, but to be able to verify 
if there is an acknowledge, it is necessary to read the device after it. To check the 
acknowledgement it is necessary to activate the control line is ack? and bus write, so 
that the interface can write to the bus the value 00 for a negative acknowledge, or FF 
for a positive acknowledge. 

8.8.6 The CPU data bus with the I/O interfaces 

Together with the I/O interface modules, also a new register is added: I OA (I/O ad- 
dress). When a device is to be reached, it is necessary to load its I/O address into the 
I OA register, before anything else can be done with the device itself. 



A simple 8-bit CPU: version "A" 439 
Figure 8.149. The CPU data bus with the IOA register and the I/O interfaces. 




br data bw 



Clk IR Clr 



bw data bt 
TT 



UZ 



br Addr bw 
RAM 



bw data br 



br data bw 



Clk MAR Clr 



^ Clr " Cll 
bw data br 



br data bw 



Clk MDR Clr 



Ho IT 



br data bw 



bw data br 



ADDR data CON 



Clk DSP Cf 



bw data br 



ADDR CON 



Clk KBD Clr 



The CPU control bus is now modified with the addition of the lines used to control 
the IOA register and the I/O interfaces. That modification has required to shift the 
line used to stop the clock. Therefore, inside the memory banks declaration code and 
inside the control word fields declaration code there are the following adaptations: 



map bank [7:0] ctrl.mO; 

microcode bank [31:0] Ctrl. ml; 

microcode bank[41:32] ctrl.m2; 

macrocode bank [7:0] ram.m3; 



field ioa_br[35]; 
field ioa_bw[3 6]; 
field io_br[37]; 
field io_bw[38]; 
field io_req[39]; 
field io_isack [ 4 0 ] ; 
field stop [41] ; 



// IOA < — bus 
// IOA — > bus 
// I/O < — bus 
// I/O — > bus 
// I/O request 
// I/O is ack? 
// stop clock 



Inside the opcode list there are new instructions and the same is for the microcode 
description. There is also a new instruction that requires two arguments: 



440 A simple 8-bit CPU: version "A' 



operands op_2 { 
// 

// [ ] [mnaanaanaam] [nnnnnnnn] 

// 

#1,#2 = { +1=#1[7:0]; +2=#2 [ 15 : 8 ] ; } ; 

}; 

op in { 



map in : 48; // read input from I/O bus 

+0 [7 : 0] =48; 
operands op_l; 

}; 

op out { 

map out : 4 9; // write output to I/O bus 

+0 [7 : 0] =49; 
operands op_l; 

}; 

op io_is_ack { 

map io_is_ack : 50; 
+0 [7 : 0] =50; 
operands op_2; 

}; 



begin microcode @ 0 






in : 






mar_br pc_bw; 


// 


MAR < — PC 


pc_Inc; 


// 


PC++ 


mdr_br ram_bw; 


// 


MDR < — RAM [mar] 


ioa_br mdr_bw; 


// 


IOA < — MDR 


io_req; 


// 




i o_b r ; 


// 


does not do anything 


a_br io_bw; 


// 


A < — I/O 


ctrl_start ctrl_load; 


// 


CNT < — 0 


out : 






mar_br pc_bw; 


// 


MAR < — PC 


pc_Inc; 


// 


PC++ 


mdr_b r r am_b w ; 


// 


MDR < — RAM [mar] 



A simple 8-bit CPU: version "A' 



441 



ioa_br mdr_bw; 




// IOA < — 


MDR 




io_br a_bw; 




// 10 < — A 




io_req; 




// 






ctrl_start ctrl_load; 




// CNT < — 


0 




io_is_ack : 










mar_br pc_bw; 




// MAR < — 


PC 




pc_Inc; 




// PC++ 






mdr_br ram_bw; 




// MDR < — 


RAM [mar ] 




ioa_br mdr_bw; 




// IOA < — 


MDR 




// 










mar_br pc_bw; 




// 


MAR < — PC 




pc_Inc; 




// 


PC++ 




mdr_br ram_bw; 




// 


MDR < — RAM [mar] 




a_br io_bw io_isack; 




// 


A < — I/O is ack 




a_br alu_f=not_a alu_bw 


f 1_ 


ar; // 


A < — NOT A 




a_br alu_f=not_a alu_bw 


f 1_ 


ar; // 


A < — NOT A 




pc_br sel_f =i f_not_zero 


sel 


_bw // 


PC = (not_zero ? MAR 


■ PC) 


ctrl_start ctrl_load; 




// 


CNT < — 0 




end 











442 



A simple 8-bit CPU: version "A" 



Figure 8.153. Match between the contents of the memory that represents the mi- 
crocode (the couple of memory banks ml and m2 inside the control unit) and the 
microcode description itself. 



o 

% 



-5; 0/ 



/ 



t f 



-o/ -0/ -q/ <$•• 
-0/ *s/ V' 



"4, 4 



5 

-o 

v.' 

to 



?. ? £ f <? 



£ 7/ 



4/ 4/ 



in: 



\ X i 1 f t ft 



mi i4" 1 i- . i- i... i- ^1 i-- 1 : h-i 1. -1 1 h>i i-:-. r; h:,. icr- i-:-: 1:1 i.i.- n in. m- im m- i.i: mi \---> 



b7 b6 b5 M b3 b2 bl bO 



( 






0 
















































0 






1 










0 






1 






0 














0 




u 






u 




















II 






0 












0 






1 








1 








0 


1 


: 


0 


0 


: 


0 






0 
















1 






1 












n 




1 


n 








1 


0 


0 


1 






1 






0 


0 






0 




0 


1 




0 






















0 
























1 








0 






0 






0 






1 






















































































0 


1 




































































0 














1 






















0 




















1 












0 










0 






0 






0 


























































0 


II 






















1 


1 



out: 



io_is_ack: 



4 i i V 



Ml 

Q.' I 

oj " 

CSV C 



^4 



0-rot A 
1 =A and B 
2=A or B 
3=A xor B 
4=A « 1 
5=A » 1 
6=A « 1 arith 
7=A » 1 arith 
8=A rot left 
9=A rot right 
A=A rot carry left 
B=A rot carry right 
C=A plus B carry 
D=A minus B borrow 
E=A plus B 
F=A minus B 



\4 



4; 

"Of 



0= 


if carry 


1= 


if not carry 


2= 


if zero 


3= 


if not zero 


4= 


if negative 


5= 


if not negative 


6= 


if overflow 


7= 


if not overflow 



0 




0 






: 


0 




: 






0 






G 






G 










G 






G 




0 


0 


0 


1 






G 






G 




1 








0 






0 










0 


















































□ 




0 




1 








0 
























































1 










1 


















0 


: 


0 




: 




: 


1 




0 






0 






G 




G 


G 










G 






G 




: 






: 


1 




0 






G 




: 








0 






0 


1 


0 


• 




0 






























1 








0 






0 






0 




0 






0 






0 






1 
















: 






0 


































































































































(J 








1 


1 




0 












































0 
















1 












0 




1 






0 












































































1 
















0 




0 






0 


















□ 
















• 




1 


■ 








1 






0 






0 






0 


0 












1 
































1 












1 






1 














0 




















i! 
















































1 
















1 








0 










(i 






(1 


































• 




0 


• 


















1 








0 






: 


















































1 










1 






















1 




1 










































1 




































0 
















0 


















1 


1 


0 


0 


0 


0 




1 






0 


• 














0 






0 






0 






















; 






0 








1 


1 


0 


0 


0 


0 




1 










































0 


























0 


































1 


0 


1 


1 




0 


1 




0 


















































































1 


1 


Ml 


MO 


b39 


b38 


b37 


b36 


b35 


b34 


b33 


b32 


b31 


b30 


b29 


b28 


b27 


b2b 


b25 


b24 


b23 


b22 


b2l 


b2U 


biy 


bis 


bl7 


bib 


bl5 


bl4 


bl3 


bl2 


bll 


blU 


b9 


b8 


b7 


b6 


b5 


M 


b3 


b2 


bl 


bo 



A simple 8-bit CPU: version "A" 443 



Table 8.154. Macroinstructions added for this version of the simple CPU. 



Syntax 


Description 


in io_address 


It reads a bvte from the I/O address sneci- 

AV 1 W 1^1 V-*- L 1 n J tv 1 J. VV 1X1 lllv 1 / tlVl Vll V U U U l_» Wl 

fled by the argument. 


out io_address 


It writes a byte to the I/O device specified 
by the argument. 


io_is_ack io_address %ref 


It reads a byte from the I/O device spec- 
iried by the first argument. 11 the byte 
read is FFi 6 that means acknowledge ad it 
jumps to the address specified as the sec- 
ond argument. 



8.8.7 Instruction "out" 

« 



Listing 8.155. Macrocode to experiment the use of out and io_is_ack. The 
program just shows the letter 'H' in a loop, without stop. The complete source 
file should be available at attachments/xcpu/xcpu-a8-out.gm . 



begin macrocode @ 0 




start : 




load_ref tcharacter 




move_mdr_a 




out 0 


// display 


check_ack : 




io_is_ack 0, #start 




jump #check_ack 




stop : 




stop 




character : 




.byte 0x48 




end 





Video: ogv http://www.youtube.com/watch?v=S9XqmTMYAj4 



444 



A simple 8-bit CPU: version "A' 



8.8.8 Instruction "in" 

Listing 8.156. Macrocode to experiment the instruction in: the keyboard is read 
and the character read is output again with the out instruction, though the dis- 
play. The complete source file should be available at attachments/xcpu/xcpu-a8- 
in.gm . 



begin 


macrocode @ 0 


start 






in 1 




not 




not 




jump_if_zero #start 




out 0 




jump #start 


stop : 






stop 


end 





Video: ogv http://www.youtube.com/watch?v=JhGoQhssWQM . 



Chapter 9 



Version XX B": optimization 

9.1 Uniform registers 446 

9.2 Module "RAM" 449 

9.3 Module "SEL" 453 

9.4 Module "ALU" 453 

9.5 Module "TTY": the terminal 454 

9.6 Module "CTRL": control unit 459 

9.7 Memories, fields, arguments and opcodes 463 

9.8 Microcode 479 

9.9 Macrocode: routine call 496 

9.10 Macrocode: keyboard input and screen output 497 

9.11 Version "B2" 498 



Here is proposed a restructuring of the simple CPU developed up to this point, to 
rearrange and simplify its operation. Version "Bl" starts from the implementation of 
uniform registers, up to an optimization of the operation, avoiding unnecessary clock 
cycles. 



Attachments 


Description 


attachments/xcpu/xcpu-bl . v 


TKGate Verilog netlist source file. 


attachments/xcpu/xcpu-bl .gm 


TKGate microcode and macrocode source 
file. 


attachments/xcpu/xcpu-bl -terminal, vpd. 
tcl 


TCL/Tk script related to the terminal mod- 
ule TTY. 


attachments/xcpu/xcpu-b2. v 


TKGate Verilog netlist source file. 


attachments/xcpu/xcpu-b2.gm 


TKGate microcode and macrocode source 
file. 


attachments/xcpu/xcpu-b2-terminal.vpd. 
tcl 


TCL/Tk script related to the terminal mod- 
ule TTY. 



446 



Version "B": optimization 



« 



Figure 9.2. Simple CPU version "Bl". 

control bus 



/ 4 



a C 


b 


SEL 


F 


t B 


0 




1 + 


+ 1+ 


1+ 


t 


o B 

Fo ALU r 

b C a 




96 

/ 



c A S K C 

TTY 

iO B oO o1 



data bus 
it 



0 B i 

IOA x 

C D c 



/ 5 



9.1 Uniform registers 

All the registers of the new simple CPU have the opportunity to increase or reduce the 
value that they contain, by one unit; moreover, they have the ability to read a datum 
from the bus (B) or from an auxiliary input (X). In order to monitor their activity, 
these registers have two outputs where LEDs could be connected: these outputs are 
activated when reading or writing is requested. 



Version "B": optimization 



447 



Figure 9.3. Generalized registers, external appearance. 

register content copy 

clear, clock 



b 0 clear 
bj clock 



auxiliary data input 



test point: active when the 
register is loading a value 









control lines 




+ 




b 0 bus read 
bj bus write 
b 2 extra read 
b^ increment 


c 


D 


C 


b 4 decrement 


X 








i 


"D 


o 












data bus 


/ 




\ test piont: active when the 
\ register is writing to the bus 



448 



Version "B": optimization 




Version "B": optimization 



449 



9.2 Module "RAM" 

The RAM module may receive the address directly from the registers PC, SP, I and 
/, without mediation, so the MAR used until the earlier version is now removed. The 
choice of the address register to read depends on the code contained in the group of 
lines of the C input. 



Figure 9.5. Module ram, external appearance. 

register PC 

clear, clock 



register J 



b 0 clear 
b l clock 



register SP 



register I 










c 


P J 


C 


S 








RAM 




I 






i 


B 


0 




test point: active when a byte is 
written inside the RAM 



data bus 



test point: active when a byte is 
read from the RAM 



The internal diagram of the RAM module changes substantially, allowing to use the 
address from the selected register, but only at the state in which this data is valid. In 
the diagram there is the addition of a module, called H, which is a register controlled 
by an enable input. Therefore, this register does not react to the change of the clock 
pulse, it is used to maintain stored a value for all the time in which the input H is 
asserted (zero, as it is a complemented input line). 



« 



450 



Version "B": optimization 



Figure 9.6. Module RAM, internal structure. 



p> 
i> 

j> 

S> y 



j>- 








D 


P 




H Q 


H 


C 



I 

A 



bus read 



8. address 
~T 



ram 



A D 



8 



O B 



bus write 



In this version of the CPU, during a clock cycle, the address used to locate a memory 
cell may not be stable, due to various factors. First of all, the address is selected, 
by a multiplexer, from four different registers, but this selection can be done at the 
start of the T phase shown inside the next figure; therefore, in this first phase the 
address received by the RAM module changes in the majority of cases. Then, when the 
clock signal changes from zero to one, the address source register might be updated in 
preparation for the next step. Therefore, the valid information from the address used 
for the RAM appears just before the clock positive edge (phase 'II'). However, when 
it is required to write a value in the RAM, the RAM itself needs to have the address 
for a certain time, during which this address should not change: this is done with the 
H module that is transparent when the signal clock is zero, while it blocks its value 
when the clock signal is active. For that reason, the RAM is enabled for receiving a 
request to read or write only during the active period of the clock signal (phase 'III'). 
When the RAM is just read, it is sufficient that the RAM has had time to provide the 
data corresponding to the address selected when the information is then loaded from 



Version "B": optimization 



451 



the bus by another register. 

Inside the figure, the graph 'A' refers to the ranges of validity of the address infor- 
mation, around the positive variation of the clock signal. The graph 'B' shows the 
situation at the output of module H, which extends the validity of the incoming ad- 
dress, because when the clock signal becomes positive, the module H blocks the value 
at its output. The graph 'C shows the period in which it is granted to the RAM mem- 
ory to change its content (RAM write). 

Figure 9.7. Functional phases for the RAM module. 















A 
















clock 




data 

valid 
< > 




data 

valid 
< ► 





c 



clock 















B 

clock 












valid data 
and held 




valid data 
and held 


clock 




III 




III 


I 




I 





held data 
K >H 



held data 
r< >\ 



II 



II 



The module H is made of simple SR flip-flops, connected so as to operate as D flip- 
flops, with the enable input. Simple flip-flops with enable input are used to avoid the 
introducing of excessive latencies. 



452 



Version "B": optimization 



Figure 9.8. Module H (hold), internal structure. 




Version "B": optimization 



453 



9.3 Module "SEL" 



« 



The selection module is not changed, except for the reorganization of the wiring and 
the addition of a diagnostic output to know when the evaluated condition is fulfilled 
(output t). 

Figure 9.9. Module SEL, internal structure. 

F a b 

V 



bO = carry 
b1 = zero 
b2 = negative 
b3 = overflow 



c>- 



3:1 
0 







control 




CO = bus write 




C3:1 =func 


c = 


01 


if carry 


c = 


03 


if not carry 


c = 


05 


if zero 


c = 


07 


if not zero 


c = 


09 


if negative 


c = 


11 


if not negative 


c = 


13 


if overflow 


c = 


15 


if not overflow 



~l 

dec 



bus write = select 



o t- c\j n "* m Ud r 



0 1 



v- 



9.4 Module "ALU" 

Also the ALU module is not substantially changed from the previous one: the control 
lines are joined together and there is a new diagnostic indicator (output o) that is 
active when the module writes to the bus. 



« 



454 



Version "B": optimization 



Figure 9.10. Module ALU, internal structure. 



b0 = carry 
b1 = zero 
k a b2 = negative 
b3 = overflow 




control 

C=01 : NOT A (Carry and Overflow unchanged) 
C=03: A AND B (Carry and Overflow unchanged) 
C=05: A OR B (Carry and Overflow unchanged) 
C=07: A XOR B (Carry and Overflow unchanged) 
C=09: logic shift left 
G=11; logic shift right 
C=13: arithmetic shift left 
C=1 5: arithmetic shift right 
C=17: rotation left 
C-19: rotation right 
C=21 : rotation left with carry 
C=23: rotation right with carry 
C=25: A plus B with carry 
C-27: A minus B with carry 
C=29: A plus B with no carry 
C=31 : A minus B with no carry 



bus write = select 



« 



9.5 Module TTY": the terminal 

The terminal, made of the keyboard-screen group, is different from the previous ver- 
sion of the simple CPU, because it is unified, as it is implemented already for the 
TKGate library. However, the unification internally maintains the circuit distinction 
of the previous version and also the same operating logic; in practice, keyboard and 
screen continue to be managed separately, but the TCL/Tk implementation code is 
made of a single module, which manifests itself in a single window during the TK- 
Gate simulation. 



Version "B": optimization 

Figure 9.11. Module tty, internal structure. 



)E>— O 



-=Q- 



cO = clear 
d = clock 

CO = bus_read 
C1 = bus_write 
C2 = request 
C3 = isack 



tastiera 



"T v i 



v- 



X 



to 



Q P J 
jk Ck 
5 g K 



=o 



Keyboard sequence: 

a) request 

b) not operate 

c) bus write 



=D rO 



jk Ck 



Ck JK _ 
K r S 



Ck JK 



Q H| 



455 



[£] When a "bus write" comes, the saved ack is cleared. 
[$] The "request" is admitted only if there is not a waiting ack previously saved. 



S_DATA 




S_REQ 




S_ACK 


terminal 


K_DATA 




KREO 




K_ACK 


CLR 



In the figure that shows the circuit of the tty module there is a delimitation between 
the two portions, related to keyboard and screen: it should be noted that the two blocks 
are activated via different addresses (input A), exactly as it is in the previous version. 
The terminal module is written in Verilog, as already done in the previous version, 
but in this case it is a single module, for keyboard and screen. In turn, the terminal 
module uses TCL/Tk code that is contained by the file 'terminal . tcl' shown im- 
mediately after. 



456 



Version "B": optimization 



Listing 9.12. Module terminal, written in Verilog. 

module terminal (K_DATA, K_REQ, K_ACK, S_DATA, S_REQ, S_ACK, CLR) ; 

output K_ACK; 
output S_ACK; 
output [7:0] K_DATA; 
input [7:0] S_DATA; 
input K_REQ; 
input S_REQ; 
input CLR; 
reg k_ready; 
reg [7:0] key ; 
reg s_ready; 

initial 
begin 

k_ready = 0; 
s_ready = 0; 
key = 0 ; 
end 

always 
begin 

@ (posedge CLR) 

k_ready = 0; 

s_ready = 0; 

key = 0 ; 
end 

initial $tkg$post ("TERMINAL", "%m") ; 

always 
begin 

@ (posedge K_REQ) ; 

# 5; 

key = $t kg$ recv ( " %m . KD " ) ; 

# 5; 



Version "B": optimization 



457 



k_ready = l'bl; 

# 5; 

@ (negedge K_REQ) ; 

# 5; 

k_ready = 1'bO; 
end 



always 
begin 

@ (posedge S_REQ) ; 

# 5; 

$tkg$send ( "%m. SD", S_DATA) ; 

# 5; 

s_ready = l'bl; 

# 5; 

@ (negedge S_REQ) ; 

# 5; 

s_ready = 1'bO; 
end 



assign S_ACK = s_ready; 
assign K_DATA = key; 
assign K_ACK = k_ready; 



endmodule 



Listing 9.13. File 'share/tkgate/vpd/terminal . tcl'. The file is similar to 
the one included in the TKGate library, for the terminal management. 

image create bitmap txtcurs -file "$bd/txtcurs .b" 

VPD :: register TERMINAL 
VPD::allow TERMINAL :: post 
VPD:: allow TERMINAL :: data 

namespace eval TERMINAL { 

# Public variables declarations: the variables $terminal_. . . 

# are arrays of which only the element $n is used; 

# that element identifies uniquely the working interface instance. 

variable terminal_w 
variable terminal_pos 



458 



Version "B": optimization 



# 

variable KD 

# Function requested by TKGate to create the interface. 

proc post {n} { 

variable terminal_w 
variable terminal_pos 

# Create the window and save the object element in a $terminal_w array element . 

set terminal_w ($n) [ VPD : : createWindow "TERMINAL $n" -shutdowncommand "TERMINAL :: impost $n"] 

# For convenience, copy the object reference inside the local 

# variable $w; then, the variable $w will be used as a reference to the object . 

set w $terminal_w ( $n ) 

text $w.txt -state disabled 

pack $w.txt 

# Put the cursor at the end of the displayed text . 

$w.txt image create end -image txtcurs 

# Bind the keyboard input, related to the object represented by 
§ $terminal_w ($n) , to the function sendChar . 

bind $w <KeyPress> "TERMINAL :: sendChar $n \"%A\"" 

# Open a reading channel , named «SD» (screen data) , 

# and associate it to the function «data»; moreover, open a 
§ writing channel, named «KD» (keyboard data) . 

if {[info exists : :tkgate_islnitialized] } { 
VPD: :outsignal $n . KD TERMINAL :: KD ( $n) 

VPD : : insignal $n.SD -command "TERMINAL :: data $n" -format %d 

} 

# Reset the character count, used to count the characters displayed 

# on screen. 

set terminal_pos ( $n) 0 

} 

# Function that receives the typing and put it into the 

# channel «KD», related to the current interface instance. 

proc sendChar {n key} { 
variable KD 

if { [string length $key ] == 1 } { 
binary scan $key c c 
set TERMINAL: : KD ($n) $c 

} 

} 

# Function that TKGate requires to destroy the interface. 

proc unpost {n} { 

variable terminal_w 
variable terminal_pos 
destroy $terminal__w ($n) 
destroy $terminal_pos ($n) 
unset terminal_w ( $n) 
unset terminal__pos ( $n) 

} 

# Function used to get the data to display on screen. 

proc data {n c} { 

variable terminal_w 
variable terminal_pos 

# For convenience, copy the object reference representing the 



Version "B": optimization 



459 



# interface, inside the variable $w. 

set w $terminal_w ($n) 
catch { 

# The variable $c contains the character to display. 

if { $c == 7 } { 
# BEL 

bell 
return 

} elseif { $c == 127 | $c == 8 } { 



# DEL I BS 

if { $terminal_pos ($n) > 0 } { 

# Delete the last displayed character, but only if the 

# characters counter is greater than zero, otherwise 

# the cursor would disappear and the next characters 

# would be located in an unvisible screen area. 
$w.txt configure -state normal 

$w.txt delete "end - 3 chars" 
$w.txt see end 

$w.txt configure -state disabled 

set terminal_pos ($n) [expr {$terminal_pos ( $n) - l}] 



# Convert the character number into a visible symbol . 

set x [format %c $c] 

# Display the symbol . 

$w.txt configure -state normal 
$w.txt insert "end - 2 chars" $x 
$w.txt see end 

$w.txt configure -state disabled 

# Update the displayed characters counter. 

set terminal_pos ( $n) [expr {$terminal_pos ($n) + l}] 



} 



return 



} elseif { $c == 13 } { 
# Convert CR to LF. 



set c 10 



} 



} 



} 



} 



9.6 Module 




control 




« 



To simplify the organization of the wiring, the control unit incorporates the generator 
of clock pulses; moreover, the generator of clock pulses incorporates the management 
of the reset signal, so that it is removed only at the moment more suitable for the 
impulse clock: up to the previous version of the simple CPU, the circuit required a 
manual reset before the CPU could work properly, but the release of the reset signal 
could happen at an unsuitable time, which made it all unstable. 



460 



Version "B": optimization 



Figure 9.14. Timing for the clear line. 



clock 



clear line 



input R 



y 

power on 



clear signal disabled 
automatically 



y 

clock pulses start 



y 

input R asserted 



y 

input R negated 



the clear line is negated after 
a little while, sincronously 



the clear line is asserted with a little delay 

The following picture shows the block diagram of the control unit that integrates 
the clock functionality. In the left part is the circuit that generates the clock pulses 
and controls the clear line. The module f div is extended compared to the previous 
version, in order to be able to divide more the frequency. The frequency selection is 
made through a multiple switch (dip switch) connected to a multiplexer that is seen at 
the top. However, the experiments with TKGate show that the CPU can operates with 
a maximum clock frequency of 1.25 MHz that is produced setting this switch to the 
value 1. 



Version "B": optimization 

Figure 9.15. Control unit with the clock generator. 




462 



Version "B": optimization 



There are different f div modules inside the control unit: the central one is used to 
count the pulses to synchronize the reset line, the rightmost is used to count clock 
pulses from the start and enable monitoring through the t output: it is therefore only 
of a diagnostic aid. 

On the right part of the figure that represents the original control unit, there is a unique 
16-bit counter (mcp) and it lacks the opportunity to restore the execution of the mi- 
crocode from the beginning (address zero). The two least significant bit of the control 
word are used to bring the clock pulse and the reset signal (clear); the same two least 
significant lines that come out from the memory that contains the microcode, are used 
to control the module itself and do not affect the rest of the CPU. This version of the 
control unit does not allow to resume the clock signal after the internal stop line is 
asserted. 



Figure 9.16. Connections to the control bus. 



.96 







/ 



o 

N 

/ 

4 



+ 8 






c D C 




c P J C 




c D C 




c D C 




a C b 




c D C 


-► 


x IR 


-► 


s RAM 
i 


-► 


X J 




xMDR 




SEL f 




x PC 




i B o 


-► 


i B o 




i B o 




i B o 




t B o 




i B o 




U * |+ 




1+ $ 1+ 




U * 1+ 




k t 1+ 


1* + 1+ 







On the picture above there are some components of the simple CPU, connected to the 
control bus. All these components have in common the c input (lowercase) and the 
C input (upper case). The c input is always connected to the first two lines of the bus 
control, from which it is obtained, respectively, the reset signal and the clock signal. 
The C input, instead, must be connected to the lines of the control bus that specifically 
relate to the module. In the case of generalized registers, these lines are always five: 
bus_read, bus_write, extra _read, increment, decrement. The PC register connects 
its C input to the lines 2 to 6 (6:2) of the control bus; the module SEL (which uses 
only four control lines) is connected to the lines 7 to 10 (10:7), and so is with the 
other components. 



Version "B": optimization 



463 



9.7 Memories, fields, arguments and opcodes 

« 

The TKGate source used to describe the contents of the memory used by the simple 
CPU, always begins with the definition of the memory dimensions, along with each 
bank name: 



map 


bank [ 7 : 


0] 


Ctrl 


. map ; 


microcode 


bank [ 3 1 


:0] 


Ctrl 


. microO ; 


microcode 


bank [ 63 


: 32] 


Ctrl 


. microl ; 


microcode 


bank [91 


: 64] 


Ctrl 


. micro2 ; 


macrocode 


bank [ 7 : 


0] 


ram . 


ram; 



In this version of the simple CPU there are some changes to the memory names, 
in order to make clearer each respective task. It should be noted that three memory 
modules, each of 32 bits, are used for the microcode word, because the control bus 
requires the use of many lines. 



field 


Ctrl [1:0] 


= {nop=0, 


stop 


=1, load=2}; 




field 


pc [ 6 : 2 ] 


= {br=l, 


bw=2 , 


xr=4, inc=8, dec=16}; 


field 


sel [10:7] 


= {if_carry=l, 


if_not_carry=3, 








if_zero=5 , 


if_not_zero=7 , 








if_negative 


=9, if_not_negative=ll , 






if_overf low 


=13, if_not_overf low= 


15}; 


field 


mdr [15 : 11] 


= {br=l, 


bw=2 , 


xr=4, inc=8, dec=16} 




field 


j [20 : 16] 


= {br=l, 


bw=2 , 


xr=4, inc=8, dec=16} 




field 


ram [24 :21] 


= {br=l, 


bw=2 , 


p=0, i=4, j=8, s=12} 




field 


ir [29:25] 


= {br=l, 


bw=2 , 


xr=4, inc=8, dec=16} 




field 


sp [34 : 30] 


= {br=l, 


bw=2 , 


xr=4, inc=8, dec=16} 




field 


i [39 : 35] 


= {br=l, 


bw=2 , 


xr=4, inc=8, dec=16} 




field 


b [44 : 40] 


= {br=l, 


bw=2 , 


xr=4, inc=8, dec=16} 




field 


fl [49 : 45] 


= {br=l, 


bw=2 , 


xr=4, inc=8, dec=16} 




field 


alu [54 : 50] 


= {not=l, 


and= 


3, or=5, xor=7, lshl= 


9, lshr=ll, 






ashl=13, ashr=15, rotl=17, rotr= 


19, rotcl=21, 






rotcr= 


=23, add_c=25, sub_b=2 7, add=2 9, sub=31}; 


field 


a [59 : 55] 


= {br=l, 


bw=2 , 


xr=4, inc=8, dec=16}; 


field 


ioa [64 : 60] 


= {br=l, 


bw=2 , 


xr=4, inc=8, dec=16}; 


field 


ioc [68 : 65] 


= {br=l, 


bw=2 , 


req=4, isack=8}; 





The control word fields are written in a more compact manner. It should be noted 



464 



Version "B": optimization 



that values that can be represented in each field may be added with the binary OR 
operator. In practice, in relation to the field pc, which refers to the PC register control 
lines, both the writing to the data bus (pc=bw) and the increment (pc=inc) could be 
turned on, during the same clock cycle. 

Inside the ctrl field declaration there are the first two lines, used for the stop clock 
and microinstruction load, but it is worth to remaind that those two lines are not 
connected to the control bus outside, because in their place there are the clear and 
clock lines. 

In this version of the project it is possible to declare a null microinstruction, with 
the sole purpose of waiting a clock cycle. This microinstruction is selected with: 
ctrl=nop. 

The opcode remains 8-bit long, then, there may be a maximum of two arguments (8 
bits each): 

operands op_0 { 

- = { }; 

}; 

operands op_l { 

#1 = { +1=#1[7:0]; }; 

}; 

operands op_2 { 

#1,#2 = { +1=#1[7:0] ; +2=#2 [15 : 8] ; }; 

}; 



The opcode of the available macroinstructions is simply an integer that starts from 
zero, matching the nop instruction, ending with 255 which matches the stop instruc- 
tion. There are no other considerations. 



op nop { 


// not 


operate 


map nop: 0; 






+0 [7 : 0] =0; 






operands op_0; 

}; 






op load 


// MDR 


< — RAM[arg] 


{ 






map load : 1 ; 







Version "B": optimization 



465 



+0 [7 : 0] = 1; 
operands op_l ; 

}; 




op load_i 

{ 

map load_i : 2 ; 
+0 [7 : 0] =2; 
operands op_0; 

}; 


// MDR < — RAM[i ] 


op load_j 

{ 

map load_j : 3 ; 
+0 [7 : 0] =3; 
operands op_0; 

}; 


// MDR < — RAM[j] 


op store { 

map store: 4; 
+0 [7 : 0] =4; 
operands op_l ; 

}; 


// RAM[arg] < — MDR 


op store_i { 

map store_i: 5; 
+0 [7 : 0] =5; 
operands op_0; 

}; 


// RAM [1 ] < — MDR 


op store_j { 

map store_j : 6; 
+0 [7 : 0] =6; 
operands op_0; 

}; 


// RAM[j] < — MDR 


op cp_i j { 

map cp_i j : 7 ; 
+0 [7 : 0] =7; 
operands op_0; 


// RAM[j++] < — MDR < — RAM[i++] 



466 



Version "B": optimization 



}; 
J ' 

op cp i i { 




// RAM[i++] < — MDR < — RAM[j++] 


map cp_ji: 8; 






+0 [7 : 0] =8; 






operands op 0 ; 

}; 






op mv_mdr_a { 




// A < — MDR 


map mv_mdr_a : 


9; 




+0 [7 : 0] =9; 






ODerands od 0; 

}; 






J ' 

op mv_mdr_b { 




// B < — MDR 


map mv_mdr_b : 


10; 




+0 [7 : 0] =10; 






operands od 0; 

}; 






J ' 

op mv_mdr_fl { 




// FL < — MDR 


map mv_mdr_f 1 : 


ii; 




+0 [7 : 0] = 11; 






operands op_0 ; 

}; 






op mv_mdr_sp { 




// SP < — MDR 


map mv_mdr_sp : 


12; 




+0 [7 : 0] =12; 






operands op 0; 

}; 






J ' 

op mv_mdr_i { 




// I < — MDR 


map mv_mdr_i : 


13; 




+0 [7 : 0] =13; 






operands op 0 ; 

|; 






J ' 

op mv_mdr_j { 




// J" < — MDJ? 


map mv_mdr_j : 


14; 




+0 [7 : 0] =14; 







Version "B": optimization 



467 



operands op_0; 

}; 




op mv_a_mdr { 

map mv_a_mdr : 15; 
+0 [7 : 0] = 15; 
operands op_0; 

}; 


// A < — MDR 


op mv_a_b { 

map mv_a_b : 16; 
+0 [7 : 0] = 16; 
operands op_0; 

}; 


// B <— A 


op mv_a_f 1 { 

map mv_a_f 1 : 17; 
+0 [7 : 0] =17; 
operands op_0; 

}; 


// FL < — A 


op mv_a_sp { 

map mv_a_sp : 18; 
+0 [7 : 0] =18; 
operands op_0; 

}; 


// SP < — A 


op mv_a_i { 

map mv_a_i : 19; 
+0 [7 : 0] =19; 
operands op_0; 

}; 


// I <— A 


op mv_a_j { 

map mv_a_j : 20; 
+0 [7 : 0] =2 0; 
operands op_0; 

}; 


// J <— A 


j ' 

op mv_b_a { 

map mv_b_a : 21; 


// A <— B 



468 



Version "B": optimization 



+0 [7 : 0] =21; 
operands op_0; 

}; 




op mv_b_mdr { 

map mv_b_mdr : 2 2; 
+0 [7 : 0] =22; 
operands op_0; 

}; 


// MDR < — B 


op mv_b_f 1 { 

map mv_b_f 1 : 2 3; 
+0 [7 : 0] =2 3; 
operands op_0; 

}; 


// FL < — B 


op mv_b_sp { 

map mv_b_sp : 2 4; 
+0 [7 : 0] =2 4; 
operands op_0; 

}; 


// SP < — B 


op mv_b_i { 

map mv_b_i : 2 5; 
+0 [7 : 0] =2 5; 
operands op_0; 

}; 


// I <— B 


op mv_b_j { 

map mv_b_j : 2 6; 
+0 [7 : 0] =26; 
operands op_0; 

}; 


// J <— B 


op mv_f l_a { 

map mv_f l_a : 2 7; 
+0 [7 : 0] =2 7; 
operands op_0 ; 

}; 


// A < — FL 


op mv_f l_b { 


// B < — FL 



Version "B": optimization 



469 



map mv_f l_b : 2 8; 
+0 [7 : 0] =2 8; 
operands op_0; 

}; 




op mv_f l_mdr { 

map mv_f l_mdr : 2 9; 
+0 [7 : 0] =2 9; 
operands op_0; 

}; 


// MDR < — FL 


op mv_fl_sp { 

map mv_f l_sp : 3 0; 
+0 [7 : 0] =30; 
operands op_0; 

}; 


// SP < — FL 


op mv_f l_i { 

map mv_fl_i: 31; 
+0 [7 : 0] =31; 
operands op_0; 

}; 


// I < — FL 


op mv_fl_j { 

map mv_f l_j : 32; 
+0 [7 : 0] =32; 
operands op_0; 

}; 


// J < — FL 


op mv_sp_a { 

map mv_sp_a : 33; 
+0 [7 : 0] =33; 
operands op_0; 

}; 


// A < — SP 


op mv_sp_b { 

map mv_sp_b : 34; 
+0 [7 : 0] =34; 
operands op_0; 

}; 


// B < — SP 



470 



Version "B": optimization 



op mv_sp_fl { 

map mv_sp_f 1 : 3 5; 
+0 [7 : 0] = 35; 
operands op_0; 

}; 


// FL < — SP 


op mv_sp_mdr { 

map mv_sp_mdr : 3 6; 
+0 [7 : 0] = 3 6; 
operands op_0; 

}; 


// MDR < — SP 


op mv_sp_i { 

map mv_sp_i : 37; 
+0 [7 : 0] =37; 
operands op_0; 

}; 


// I < — SP 


op mv_sp_j { 

map mv_sp_j : 38; 
+0 [7 : 0] =38; 
operands op_0; 

}; 


// J < — SP 


op mv_i_a { 

map mv_i_a : 3 9; 
+0 [7 : 0] =3 9; 
operands op_0; 

}; 


// A <— I 


op mv_i_b { 

map mv_i_b : 4 0; 
+0 [7 : 0] =4 0; 
operands op_0; 

}; 


// B <— I 


op mv_i_f 1 { 

map mv_i_f 1 : 41; 
+0 [7 : 0] =41; 
operands op_0; 


// FL < — I 



Version "B": optimization 



471 



}; 

op mv_i_sp { 

map mv_i_sp: 42; 
+0 [7 : 0] = 42; 
operands op_0; 

}; 


// SP < — I 


op mv_i_mdr { 

map mv_i_mdr : 4 3; 
+0 [7 : 0] = 43; 
operands op_0; 

}; 


// MDR < — I 


op mv_i_j { 

map mv_i_j : 44; 
+0 [7 : 0] =44; 
operands op_0; 

}; 


// J <— I 


op mv_j_a { 

map mv_j_a: 45; 
+0 [7 : 0] =45; 
operands op_0; 

}; 


// A <— J 


op mv_j_b { 

map mv_ j_b : 4 6; 
+0 [7 : 0] =46; 
operands op_0; 

}; 


// B <— J 


op mv_j_fl { 

map mv_j_fl: 47; 
+0 [7 : 0] =47; 
operands op_0; 

}; 


// FL < — J 


op mv_j_sp { 

map mv_j_sp: 48; 
+0 [7 : 0] =4 8; 


// SP < — J 



472 



Version "B": optimization 



operands op_0; 

}; 




op mv_j_i { 

map mv_ j_i : 4 9; 
+0 [7 : 0] = 4 9; 


// I < — J 


operands op_0; 

}; 




op mv_j_mdr { 

map mv_j_mdr: 50; 
+0 [7 : 0] = 50; 


// MDR < — J 


operands op_0; 

}; 




op j ump { 

map j ump : 51; 
+0 [7 : 0] =51; 


// PC < — ara 


operands op_l; 

}; 




op j ump_c { 

map j ump_c : 52; 
+ 0 [7 : 0] =52; 


// if carry, PC < — arg 


operands op_l ; 

}; 




op jump nc { 

map j ump_n c : 53; 
+0 [7 : 0] =53; 


// if not carry, PC < — arg 


operands op_l ; 

}; 




op jump_z { 

map j ump_z : 54; 
+0 [7 : 0] =54; 


// if zero, PC < — arg 


operands op_l ; 

}; 




j ' 

op j ump_n z { 

map j ump_n z : 55; 


// if not zero, PC < — arg 



Version "B": optimization 



473 



+0 [7 : 0] = 55; 
operands op_l ; 

}; 








op j ump_n { 

map j ump_n : 5 6; 
+0 [7 : 0] = 5 6; 
operands op_l ; 

}; 


// if negative, PC < — 


arg 




op jump_nn { 

map j ump_nn : 57; 
+0 [7 : 0] =57; 
operands op_l ; 

}; 


// if not negative, PC 


< — 


arg 


op j ump_o { 

map j ump_o : 5 8; 
+0 [7 : 0] =58; 
operands op_l ; 

}; 


//if overflow, PC < — 


arg 




op jump_no { 

map j ump_no : 5 9; 
+0 [7 : 0] =5 9; 
operands op_l ; 

}; 


// if not overflow, PC 


< — 


arg 


op call { 

map call : 60; 
+0 [7 : 0] =60; 
operands op_l; 

}; 








op call_i { 

map call_i: 61; 
+0 [7 : 0] =61; 
operands op_0 ; 

}; 


// call I 






op call_j { 


// call J 







474 



Version "B": optimization 



map call_ j : 62 ; 
+0 [7 : 0] = 62; 
operands op_0; 

}; 

op return { 

map return : 63; 
+0 [7 : 0] = 63; 
operands op_0; 

}; 

op push_mdr { 

map push_mdr: 64; 
+0 [7 : 0] =64; 
operands op_0; 

}; 

op push_a { 

map push_a: 65; 
+0 [7 : 0] =65; 
operands op_0; 

}; 

op push_b { 

map push_b: 66; 
+0 [7 : 0] =66; 
operands op_0; 

}; 

op push_fl { 

map push_fl: 67; 
+0 [7 : 0] =67; 
operands op_0; 

}; 

op push_i { 

map push_i: 68; 
+0 [7 : 0] =68; 
operands op_0; 

}; 



Version "B": optimization 



475 



op push j 


i 




map push 


_j = 


69; 


+0 [7 : 0] = 


69; 




operands 

}; 


OD 


0; 


J i 

od dod mdr 


I 




map pop_ 


mdr 


: 70; 


+0 [7 : 0] = 


70; 




operands 

}; 


op 


_0; 


j ' 

op pop a { 






map pop_ 


a : 


71; 


+0 [7 : 0] = 


71; 




operands 

}; 


OD 

IT 


0; 


op pop b { 






map pop_ 


b: 


72; 


+0 [7 : 0] = 


72; 




operands 

}; 


OD 

It 


0; 


J ' 

op pop f 1 






map pop_ 


fl : 


73; 


+0 [7 : 0] = 


73; 




operands 

}; 


op 


_0; 


J ' 

OD DOD i 1 






map pop_ 


i : 


74; 


+0 [7 : 0] = 


74; 




operands 

}; 


op 


_0; 


j ' 

OD DOD i 1 






map pop_ 


i : 


75; 


+0 [7 : 0] = 


75; 




operands 


op 


_0; 



476 



Version "B": optimization 



}; 

op not { 






map not : 


7 6; 




+0 [7 : 0] = 


7 6; 




operands 

}; 


OP 
w tr — 


0; 


J i 

op and { 






map and: 


77; 




+0 [7 : 0] = 


77; 




operands 

}; 


op 


0; 


j ' 

op or { 






map or: 


78; 




+0 [7 : 0] = 


78; 




operands 

}; 


op 


0; 


j ' 

op xor -f 






map xor: 


7 9; 




+0 [7 : 0] = 


7 9; 




operands 

}; 


op 


0; 


J i 

op lshl { 






map lshl 


: 80 


} 


+0 [7 : 0] = 


80; 




operands 

}; 


OP 
w tr — 


0; 


J i 

op lshr { 






map lshr 


: 81 


} 


+0 [7 : 0] = 


81; 




operands 

}; 


OP 


0; 


J i 

op ashl { 






map ashl 


: 82 


} 


+0 [7 : 0] = 


82; 





Version "B": optimization 



477 



operands 

}; 


op 


0; 


J ' 

op ashr { 






map ashr 


: 83; 


+0 [7 : 0] = 


83; 




operands 

}; 


op 


_0; 


op rotl { 






map rotl 


: 8 


4; 


+0 [7 : 0] = 


84; 




operands 

}; 


op 


_0; 


J ' 

op rotr { 






map rotr 


: 85; 


+0 [7 : 0] = 


85; 




operands 

}; 


op 


_0; 


op rotcl { 






map rotcl: 


8 6; 


+0 [7 : 0] = 


86; 




operands 

}; 


op 


_0; 


op rotcr { 






map rotcr: 


87; 


+0 [7 : 0] = 


87; 




operands 

}; 


op 


_0; 


op add_c { 






map add_ 


c : 


88; 


+0 [7 : 0] = 


88; 




operands 

}; 


op 


_0; 


op sub_b { 






map sub_ 


b: 


8 9; 



478 



Version "B": optimization 



+0 [7 : 0] = 8 9; 
operands op_0; 

}; 

op add { 

map add: 90; 
+0 [7 : 0] = 90; 
operands op_0; 

}; 

op sub { 

map s ub : 91; 
+0 [7 : 0] =91; 
operands op_0; 

}; 

op in { 

map in : 92; 
+0 [7 : 0] =92; 
operands op_l; 

}; 

op out { 

map out : 93; 
+0 [7 : 0] =93; 
operands op_l; 

}; 

op is_ack { 

map is_ack: 94; 
+0 [7 : 0] =94; 
operands op_2; 

}; 

op stop { 

map stop : 2 55; 
+0 [7 : 0] =255; 
operands op_0; 

}; 



Version "B": optimization 



479 



9.8 Microcode 



« 



Inside the microcode description section, the first instructions are used to load the first 
opcode, but in this version, only one clock cycle is needed: 



begin microcode @ 0 






// 






ir=br ram=bw ram=p pc=inc ctrl=load; 


// 


IR <- RAM[pc++] , 




// 


jump MAP [ir] ; 



The IR register loads from the data bus what is output from the RAM module, which 
in turn receives the address from the PC register, which is also post-incremented. In 
addition to this, it is required to the control unit to update its microprogram-counter 
(mpc) with the value coming from the memory ctrlmap, associated to the address 
that represents the opcode. All this can be done in a single clock cycle because the 
structure of the CPU has changed from the previous version. Should be considered the 
different phases of the clock cycle, which intervene in different ways in the control 
unit with respect to the components that are then connected to the control bus, as 
shown in the next picture. 

Figure 9.22. Fetch clock cycle. 



the control bus is updated 
with the microcode to be 
executed and the MPC 
is prepared to load a 
value, but not immediately 



in the data bus is already available 
the opcode read from the RAM 



the IR register is updated with the value 
read from the data bus 



CPU clock 



clock seen by the microprogram counter 



the microprogram counter MPC loads the incoming value, 

which is the microcode address that 

implements the opcode received from the IR register 



the PC value is incremented 



Therefore, with only one clock cycle, it takes place what is known as fetch. In the 



480 



Version "B": optimization 



following instructions description, at the end of each procedure the fetch microin- 
struction is repeated, without the need to restart the microprogram counter mpc to the 
first microinstruction, as it was necessary in previous versions of the simple CPU. In 
practice, for the macroinstruction nop there is only the fetch microinstruction: 



nop : 










ir=br ram=bw ram=p 


pc=inc ctrl= 


load; // fetch 


[t follows the description of the other macroinstructions: 


load : 










i=br ram=bw ram=p pc=inc; 






// 


I <- RAM[pc++]; 


mdr=br ram=bw ram=i; 






// 


MDR <- RAM[i ] ; 


ir=br ram=bw ram=p pc=inc 


ctrl = 


load; 


// 


fetch 


load_i : 










mdr=br ram=bw ram=i; 






// 


MDR <- RAM[i ] ; 


ir=br ram=bw ram=p pc=inc 


ctrl = 


load; 


// 


fetch 


load_j : 










mdr=br ram=bw ram=j; 






// 


MDR <- RAM[j ] ; 


ir=br ram=bw ram=p pc=inc 


ctrl = 


load; 


// 


fetch 


store : 










i=br ram=bw ram=p pc=inc; 






// 


I <- RAM[pc++]; 


ram=br ram=i mdr=bw; 






// 


RAM[i] <- MDR; 


ir=br ram=bw ram=p pc=inc 


ctrl = 


load; 


// 


fetch 


store_i : 










ram=br ram=i mdr=bw; 






// 


RAM[i] <- MDR; 


ir=br ram=bw ram=p pc=inc 


ctrl = 


load; 


// 


fetch 


store_j : 










ram=br ram=j mdr=bw; 






// 


RAM[j] <- MDR; 


ir=br ram=bw ram=p pc=inc 


ctrl = 


load; 


// 


fetch 


cp_i j : 










mdr=br ram=bw ram=i i=inc 


r 




// 


MDR <- RAM[i++ ] ; 


ram=br ram=j mdr=bw j=inc 


r 




// 


RAM[j++] <- MDR; 


ir=br ram=bw ram=p pc=inc 


ctrl = 


load; 


// 


fetch 


cp_ji : 










mdr=br ram=bw ram=j j=inc 






// 


MDR <- RAM[j++ ] ; 


ram=br ram=i mdr=bw i=inc 






// 


RAM[i++] <- MDR; 


ir=br ram=bw ram=p pc=inc 


ctrl = 


load; 


// 


fetch 


mv_mdr_a : 










a=br mdr=bw; 






// 


A <- MDR; 


ir=br ram=bw ram=p pc=inc 


ctrl = 


load; 


// 


fetch 


mv_mdr_b : 










b=br mdr=bw; 






// 


B <- MDR; 



Version "B": optimization 



481 





ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_mdr_f 1 : 




















fl=br 


mdr=bw; 












// 


FL <- MDR; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_mdr_sp : 




















sp=br 


mdr=bw; 












// 


SP <- MDR; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_mdr_i : 




















i=br mdr=bw; 












// 


I <- MDR; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_mdr_ j : 




















j=br mdr=bw; 












// 


J <- MDR; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_a_mdr : 




















mdr=br 


a=bw; 












// 


MDR <- A; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_a_b : 




















b=br a 


=bw; 












// 


B <- A; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_a_f 1 : 




















f l=br 


a=bw; 












// 


FL <- A; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_a_sp : 




















sp=br 


a=bw; 












// 


SP <- A; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_a_i : 




















i=br 


a=bw; 












// 


I <- A; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_a_j : 




















j=br 


a=bw; 












// 


J <- A; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_b_a : 




















a=br b 


=bw; 












// 


A <- B; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_b_mdr : 




















mdr=br 


b=bw; 












// 


MDR <- B; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_b_f 1 : 




















fl=br 


b=bw; 












// 


FL <- B; 




ir=br 


ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_b_sp : 




















sp=br 


b=bw; 












// 


SP <- B; 



482 



Version "B": optimization 





ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_b_i: 

i=br b=bw; 












// 


I <- B; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_b_j: 

j=br b=bw; 












// 


J <- B; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_fl_a: 

a=br fl=bw; 












// 


A <- FL; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_fl_b: 

b=br fl=bw; 












// 


B <- FL; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_f l_mdr : 

mdr=br fl=bw; 












// 


MDR <- FL; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_fl_sp: 

sp=br fl=bw; 












// 


SP <- FL; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_f l_i : 

i=br fl=bw; 












// 


I <- FL; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


-f l_j : 

j=br fl=bw; 












// 


J <- FL; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_sp_a : 

a=br sp=bw; 












// 


A <- SP; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_sp_b : 

b=br sp=bw; 












// 


B <- SP; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_sp_f 1 : 

fl=br sp=bw; 












// 


FL <- SP; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_sp_mdr : 

mdr=br sp=bw; 












// 


MDR <- SP; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_sp_i : 

i=br sp=bw; 












// 


I <- SP; 




ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ 


_sp_j : 

j=br sp=bw; 












// 


J <- SP; 



Version "B": optimization 



483 



ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_i_a : 
















a=br i=bw; 












// 


A <- I; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_i_b : 
















b=br i=bw; 












// 


B <- I; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_i_f 1 : 
















fl=br i=bw; 












// 


FL <- I; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_i_sp : 
















sp=br i=bw; 












// 


SP <- I; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_i_mdr : 
















mdr=br i=bw; 












// 


MDR <- I; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_i_ j : 
















j=br i=bw; 












// 


J <- I; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ j_a : 
















a=br j=bw; 












// 


A <- J; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ j_b : 
















b=br j=bw; 












// 


B <- J; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_j_f 1 : 
















fl=br j=bw; 












// 


FL <- J; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ j_sp : 
















sp=br j=bw; 












// 


SP <- J; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ j_i : 
















i=br j=bw; 












// 


I <- J; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


mv_ j_mdr : 
















mdr=br j=bw; 












// 


MDR <- J; 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


jump : 
















i=br pc=bw; 












// 


I <- PC 


pc=br ram=bw 


ram=i ; 










// 


PC < — RAM[i ] 


ir=br ram=bw 


ram=p 


pc= 


inc 


ctrl = 


load; 


// 


fetch 


j ump_c : 

















484 



Version "B": optimization 



mdr=br ram=bw ram=p pc=inc; 




// 


MDR < — RAM[pc++] 


pc=br sel=if_carry ; 




// 


PC = ( carry ?MDR :PC) 


ir=br ram=bw ram=p pc=inc ctrl= 


load; 


// 


fetch 


j ump_n c : 








mdr=br ram=bw ram=p pc=inc; 




// 


MDR < — RAM[pc++] 


pc=br sel=if_not_carry; 




// 


PC = (not_carry?MDR:PC) 


ir=br ram=bw ram=p pc=inc ctrl= 


load; 


// 


fetch 


jump_z : 








mdr=br ram=bw ram=p pc=inc; 




// 


MDR < — RAM[pc++] 


pc=br sel=if_zero; 




// 


PC = (zero?MDR:PC) 


ir=br ram=bw ram=p pc=inc ctrl= 


load; 


// 


fetch 


jump_nz : 








mdr=br ram=bw ram=p pc=inc; 




// 


MDR < — RAM[pc++] 


pc=br sel=if_not_zero; 




// 


PC = (not_zero?MDR:PC) 


ir=br ram=bw ram=p pc=inc ctrl= 


load; 


// 


fetch 


j ump_n : 








mdr=br ram=bw ram=p pc=inc; 




// 


MDR < — RAM[pc++] 


pc=br sel=if_negative; 




// 


PC = (negative?MDR:PC) 


ir=br ram=bw ram=p pc=inc ctrl= 


load; 


// 


fetch 


jump_nn : 








mdr=br ram=bw ram=p pc=inc; 




// 


MDR < — RAM[pc++] 


pc=br sel=if_not_negative; 




// 


PC = (not_negative?MDR:PC) 


ir=br ram=bw ram=p pc=inc ctrl= 


load; 


// 


fetch 


j ump_o : 








mdr=br ram=bw ram=p pc=inc; 




// 


MDR < — RAM[pc++] 


pc=br sel=if_overf low; 




// 


PC = (overflow?MDR:PC) 


ir=br ram=bw ram=p pc=inc ctrl= 


load; 


// 


fetch 


jump_no : 








mdr=br ram=bw ram=p pc=inc; 




// 


MDR < — RAM[pc++] 


pc=br sel=if_not_overf low; 




// 


PC = (not_overflow?MDR:PC) 


ir=br ram=bw ram=p pc=inc ctrl= 


load; 


// 


fetch 


call: 








i=br ram=bw ram=p pc=inc sp=dec 


r 


// 


I <- RAM[pc++], SP — ; 


ram=br ram=s pc=bw; 




// 


RAM[sp] <- PC; 


pc=br i=bw; 




// 


PC <- J; 


ir=br ram=bw ram=p pc=inc ctrl= 


load; 


// 


fetch 


call_i : 








sp=dec; 




// 


SP—; 


ram=br ram=s pc=bw; 




// 


RAM[sp] <- PC; 


pc=br i=bw; 




// 


PC <- I; 


ir=br ram=bw ram=p pc=inc ctrl= 


load; 


// 


fetch 


call_j : 









Version "B": optimization 



485 



sp=dec; 








// 


SP—; 




ram=br ram=s 


pc=bw; 






// 


RAM[sp] 


<- PC; 


pc=br j=bw; 








// 


PC <- J; 




ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




return : 














pc=br ram=bw 


ram=s sp=inc; 






// 


PC <- RAM[sp++]; 


ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




push_mdr : 














sp=dec; 








// 


SP—; 




ram=br ram=s 


mdr=bw; 






// 


RAM[sp] 


<- MDR; 


ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




push_a : 














sp=dec; 








// 


SP—; 




ram=br ram=s 


a=bw; 






// 


RAM[sp] 


<- A; 


ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




push_b : 














sp=dec; 








// 


SP—; 




ram=br ram=s 


b=bw; 






// 


RAM[sp] 


<- B; 


ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




push_f 1 : 














sp=dec; 








// 


SP—; 




ram=br ram=s 


f l=bw; 






// 


RAM[sp] 


<- FL; 


ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




push_i : 














sp=dec; 








// 


SP—; 




ram=br ram=s 


i=bw; 






// 


RAM[sp] 


<- i; 


ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




push_j : 














sp=dec; 








// 


SP—; 




ram=br ram=s 


j=bw; 






// 


RAM[sp] 


<- J; 


ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




pop_mdr : 














mdr=br ram=bw ram=s sp=inc 


r 




// 


MDR <- RAM[sp++]; 


ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




pop_a : 














a=br ram=bw 


ram=s sp=inc; 






// 


A <- RAM[sp++] ; 


ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




pop_b : 














b=br ram=bw 


ram=s sp=inc; 






// 


B <- RAM[sp++] ; 


ir=br ram=bw 


ram=p pc=inc 


ctrl = 


load; 


// 


fetch 




pop_f 1 : 














fl=br ram=bw 


ram=s sp=inc; 






// 


FL <- RAM[sp++]; 



486 



Version "B": optimization 



ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


pop_i : 












i=br ram=bw ram=s sp= 


inc; 






// 


I <- RAM[sp++]; 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


pop_j : 












j=br ram=bw ram=s sp= 


inc; 






// 


J <- RAM[sp++] ; 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


not : 












a=br alu=not fl=xr; 








// 


A <- NOT A; 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


and : 












a=br alu=and fl=xr; 








// 


A <- A AND B 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


or : 












a=br alu=or fl=xr; 








// 


A <- A OR B 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


xor : 












a=br alu=xor fl=xr; 








// 


A <- A XOR B 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


lshl : 












a=br alu=lshl fl=xr; 








// 


A <— A « 1 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


lshr : 












a=br alu=lshr fl=xr; 








// 


A <— A » 1 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


ashl : 












a=br alu=ashl fl=xr; 








// 


A <- A*2 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


ashr : 












a=br alu=ashr fl=xr; 








// 


A <- A/2 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


rotl : 












a=br alu=rotl fl=xr; 








// 


A <- rotl (A) 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


rotr : 












a=br alu=rotr fl=xr; 








// 


A <- rotr (A) 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


rotcl : 












a=br alu=rotcl fl=xr; 








// 


A <- rotcl (A) 


ir=br ram=bw ram=p pc 


=inc 


ctrl = 


load; 


// 


fetch 


rotcr : 












a=br alu=rotcr fl=xr; 








// 


A <- rotcr (A) 



Version "B": optimization 



487 





ir=br ram=bw ram=p pc= 


inc 


ctrl = 


load; 


// 


fetch 


add 


_c : 

a=br alu=add_c fl=xr; 








// 


A <- A+B+carry 




ir=br ram=bw ram=p pc= 


inc 


ctrl = 


load; 


// 


fetch 


sub. 


_b: 

a=br alu=sub_b fl=xr; 








// 


A <- A-B-borrow 




ir=br ram=bw ram=p pc= 


inc 


ctrl = 


load; 


// 


fetch 


add 


a=br alu=add fl=xr; 








// 


A <- A+B 




ir=br ram=bw ram=p pc= 


inc 


ctrl = 


load; 


// 


fetch 


sub 


a=br alu=sub fl=xr; 








// 


A <- A-B 




ir=br ram=bw ram=p pc= 


inc 


ctrl = 


load; 


// 


fetch 


in : 
















ioa=br ram=bw ram=p pc 


= inc 


r 




// 


IOA <- RAM[pc++] ; 




ioc=req; 








// 


I/O request; 




ctrl=nop; 








// 


does not do anything 




a=br ioc=bw; 








// 


A <- I/O 




ir=br ram=bw ram=p pc= 


inc 


ctrl = 


load; 


// 


fetch 


out 
















ioa=br ram=bw ram=p pc 


= inc 


r 




// 


IOA <- RAM[pc++]; 




ioc=br a=bw; 








// 


I/O <- A 




ioc=req; 








// 


I/O request; 




ir=br ram=bw ram=p pc= 


inc 


ctrl = 


load; 


// 


fetch 


is_ 


ack : 














ioa=br ram=bw ram=p pc 


= inc 


r 




// 


IOA <- RAM[pc++]; 




mdr=br ram=bw ram=p pc 


= inc 


r 




// 


MDR <- RAM[pc++]; 




a=br ioc=bw ioc=isack; 








// 


A <- I/O is ack; 




a=br alu=not fl=xr; 








// 


A <- NOT A; 




a=br alu=not fl=xr; 








// 


A <- NOT A; 




pc=br sel=if_not_zero; 








// 


PC = (not_zero?MDR:PC) ; 




ir=br ram=bw ram=p pc= 


inc 


ctrl = 


load; 


// 


fetch 


stop : 














ctrl=stop; 








// 


stop clock 




//if resumed: 














ir=br ram=bw ram=p pc= 


inc 


ctrl = 


load; 


// 


fetch 


end 















The set of macroinstructions has changed slightly and is also extended, taking into 
account the changes to the CPU, as described in the following table. 



488 Version "B": optimization 



Table 9.25. Macroinstruction list for the current simple CPU. 



Syntax 


Clock 
cycles 


Description 


nop 


1 


Do nothing: just fetch the next in- 
struction. 


load address 


3 


The instruction loads the argument 
into the / register and then loads into 
the MDR register the memory con- 
tent at the specified address. 


load_i 
load_j 


2 


The instruction loads into the MDR 
register the memory content at the 
address specified by the I or J reg- 
isters. 


store address 


3 


The instruction loads the argument 
into the / register and then it writes 
the MDR content into the memory, 
at the address specified. 


store_i 
store_j 


2 


The instruction writes the MDR con- 
tent into memory, at the address 
specified by the I or J registers. 


cp_i j 
cp_ji 


3 


The first instruction copies the mem- 
ory content from the address speci- 
fied by the / register to the address 
specified by the J register. The sec- 
ond instruction does the opposite. 



Version "B": optimization 



489 



Syntax 


Clock 
cycles 


Description 


mv_mdr_a 






mv_mdr_b 






mv_mdr_f 1 




Copy the content of the MDR regis- 




2 


ter to the register A, B, FL, SP, I or 


mv_mdr_sp 




J. 


mv_mdr_i 






mv_mdr_ j 






mv_a_mdr 






mv_a_b 






mv_a_f 1 




Copy the content of the A register to 




2 


the register MDR, B, FL, SP, I or 


mv_a_sp 






mv_a_i 






mv_a_j 







490 



Version "B": optimization 



Syntax 


Clock 
cycles 


Description 


mv_b_a 






mv_b_mdr 






mv_b_f 1 




Copy the content of the B register to 




2 


the register A, MDR, FL, SP, I or 


mv_b_sp 




J. 


mv_b_i 






mv_b_j 






mv_f l_a 






mv_f l_b 






mv_f l_mdr 




Copy the content of the FL register 




2 


to the register A , B, MDR, SP, I or 


mv_f l_sp 






mv_f l_i 






mv_f l_j 







Version "B": optimization 



491 



Syntax 


Clock 
cycles 


Description 


mv_sp_a 






mv_sp_b 






mv_sp_f 1 




Copy the content of the SP register 




2 


to the register A , B, FL, MDR, I or 


mv_sp_mdr 




/. 


mv_sp_i 






mv_sp_ j 






mv_i_a 






mv_i_b 






mv_i_f 1 




Copy the content of the / register to 




2 


the register A , B, FL, SP, MDR or 


mv_i_sp 






mv_i_mdr 






mv_i_ j 







492 



Version "B": optimization 



Syntax 


Clock 
cycles 


Description 


mv_j_a 






mv_j_b 






mv_j_f 1 
mv_ j_sp 


2 


Copy the content of the J register 
to the register A, B, FL, SP, I or 
MDR. 


mv_ j_i 






mv_j_mdr 






j ump address 


3 


Jump to the specified address: it puts 
tne argument mio tne i regisier ana 
then jumps to the instruction at that 

aUUlCas. 


jump_c address 






jump_nc address 






j u mp_ z address 
j u mp_n z address 
jump_n address 
jump_nn address 


3 


These instructions put the argument 
inside the MDR register, then, if the 
condition implied by the name is 
true, they jumps to the instruction at 
the address specified. The conditions 
are in this order: carry, not carry, 
zero, not zero, negative, not negative, 
overflow, not overflow. 


j ump_o address 






jump_no address 







Version "B": optimization 



493 



Syntax 


Clock 
cycles 


Description 


call address 


4 


Call a procedure: it puts the argu- 
ment into the / register and it decre- 
ment the SP register, then, it saves 
the PC register to the memory ad- 
dress contained inside the SP resis- 
ter (it is a push). Then it jumps to the 
address specified. 


call_i 
call_j 


4 


Call a procedure: it decrement the 
SP register, then, it saves the PC 
register to the memory address con- 
tained inside the SP register (it is a 
push). Then it jumps to the address 
specified by the register I or J. 


return 




Return from procedure call: it reads 
the value contained in memory at the 
SP nosition and it writes that value 

KJ A. l.J 1 HV11 CXI 1 V_l 1 x. VV 11 IvJ 111 LI I V CI 1 CI \s 

to the PC register, then increment 
the SP register. 


push_mdr 






push_a 






push_b 
push_f 1 
push_sp 


3 


Save a register on to the stack: it 
decrements the SP register, then, at 
the new address specified by the 
SP register, it writes in memory the 
value of the register named as an ex- 
tention to the instruction name. That 
is: MLfK, A, tf, r L, SP, 1 or J . 


push_i 






push_j 







494 



Version "B": optimization 



Syntax 


Clock 
cycles 


Description 


pop_mdr 






pop_a 






pop_b 
pop_f 1 
pop_sp 


3 


Restore a register from the stack: it 
copies inside the specified register 
the memory content at the position 
specified by the SP register, then it 
increments the same SP register. 


pop_i 






pop_j 






not 


2 


A=~A 


and 

or 

xor 


2 


A =A & B 
A =A \ B 
A = A A B 


lshl 
lshr 


2 


A = left or right logic shift of A 


ashl 
ashr 


2 


A = left or right arithmetic shift of A 



Version "B": optimization 



495 



Syntax 


Clock 
cycles 


Description 


rot 1 
rot 1 


2 


A = left or right rotation of A 


rotcl 
rotcl 


2 


A = left or right rotation with carry 
of A 


add_c 
sub_b 


2 


A = A+B+carry 
A = A-B -carry 


add 
sub 


2 


A =A+B 
A =A-B 


in io_address 


5 


Read from I/O device' it read from 

X. X. W CX V-X 1 1 1X1 X / > r V1V V X. V-'V-' • 1 \- 1 VllVl 1 1 VI 111 

the I/O address specified and the re- 
sult is placed inside register A . 


out io_address 


4 


Write to an I/O device* it writes the 
content of register A to the I/O de- 
vice with the address specified. 


i s _a c k io_address address 


7 


Jump if previous I/O operation is ac- 
knowledged: it load the specified I/O 
address into the MDR register and, 
if the device returns a positive ac- 
knowledge, it jumps to the last ar- 
gument address The ODeration de- 
stroys the A register content and up- 
dates the flags. 


stop 


1 


Halt: it stops the clock. 



The following sections provide some examples to verify the operation of macroin- 



496 Version "B": optimization 

structions with the current version of the simple CPU. The examples are combined 
with videos where also the RAM access is highlighted. 

9.9 Macrocode: routine call 



D6yin III a. CIOCOQS IS U 




b Lai L • 




lOaQ ff Qa.TL a. O 


/ / irJ.clCG uilG SuclCK . 


ILL V ILLU. J_ o £J 




Call ff s um 


/ / all M ^*\ 4— * 7 » ^ W /»^ ^» vim # 1 

// Laii uiie ruijcuiOij sujiij/ . 


o L UU 




s urn : 








TYl T 7 TTl V* "Zi 

ILL V XLL(J.i d 




1 a 3 H #^3 f 3 1 

-LOciU. tfU-d-Ld. _L 




rnT 7 mr\-r "h 

ILL v 1LLL/L-L U 




3.dd 




rnT 7 a -r 
ILLv CL 1LLL/L-L 




O T" V* £^ TP — i -|— — i O 

oLUIc tfU-d-Ld. Z 




T" "h 1 1 T~ Tl 
J_ L- L-L _L 1 1 




CLd L d U • 




• U V L C \J 2\. J — L 




Ha-ha 1 • 

U.CI LCI X • 




.byte 0x12 




data_2 : 




.byte 0x00 




data_3 : 




.byte 0x30 




end 





Version "B": optimization 



497 



Figure 9.27. Data bus after the execution of the code listed above. Video: ogv 
http://www.youtube. com/watch ?v=eATz3XLYWbc 



bus di controllo 





r 


> 





1 
reset 



llll III 



lit? 



i:0 ; 



9 2f 

2 



16 



stop 



clear 



clock O" 



tR I 
i CTRL t h 



1:0 



4:21 



CDC 

Six IR 

i B o 



16 



*6 



SP xfl 

CDC 



34: 30 



t 




r 




1 


' 8 
0 


1 




n 


13 


uj 



i:0 ; 



0:15 



i 



If. 





3 




_( 



C P J c 

5 RAM 



5" 



1 0 



eh. 



□ 



if. 



10: 7 



1:0 6 



_l_ 



Jk X J 



■a 



^5 5" 



n, MDR 



B i 
i x|j_ 



B <1 



if. 



1 0 



a c b 
SEL F 

t B 0 



5" 



O B i 

FL :■: 

CDC 



9 



2 

39:35 



t 

2 

4:40 



16 



jJl HE 



2 

04|9:45 



A,. 



O B 

f ,-,MjUfi 

b c * 



t t 



PI 

54:50 



t If 



mi pc 



5" 



•3 



o B i 
A xfr 

CDC 



16 



If. 



I 59:55 



If. 



68:6 



n 
u 

7 



TTY 

iO B oO ol 



0 M 0 



bus dati 



o B i 
IOA x 

CDC 



t 

2 

64: 60 



16 







>_ 


_( 



16 



• 












1 


0 


1 


In 
u 


ril 
u 



16 



If. 



OO 


<i 1 


14 


0,- 


3c 


0 6 


1 1 


01 


11 


09 


III 


12 


Oa 


5a 


III 


i '4 


13 


10 


3f 


1 1 


L2 


23 


iO 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


20 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


05 


30 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


:■: :■: 


XX 


XX 


XX 


XX 


XX 


40 


XX 


XX 


XX 


XX 


:•: :■: 


XX 


:•: :■: 


X X 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


50 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 


XX 



Last Read Access 


Address 
Data 
Time 


06 
B'h1 

1 1.6821ms 



Last Write Access 


Address 
Data 
Time 


13 

8'h23 

10.3632ms 



ismis 



9.10 Macrocode: keyboard input and screen output 

, , « 



begin 


macrocode @ 0 






start 










in 1 


// 


Read from the keyboard. 




not 


// 


Complement two times just to update 




not 


// 


the status flags. 




jump_z #start 


// 


If the value Is zero, then repeat 






// 


the keyboard read. 




out 0 


// 


Otherwise, display the same 






// 


value on screen. 



498 



Version "B": optimization 





11117113 art" 


// Restart 


S t Op ! 




// It will never rea.ch this ooint 




stop 




end 







Figure 9.29. Keyboard input and screen output. Video: ogv Mp://www.youtube. 
com/watch ?v=m22oK22ULTwWo 



TkGate: TERMINAL main.gl33.g22 



bus di controllo 



reset r ~| a= 
ft r 



stop O ■ 



t CTRL t ajj IR 



an 1 1 □ i ran 

4: 21 J 1: 0 ^Q: iji [lO^jJl J 10; 7 J j 1 : 0 J 6 2 ' 1 [I T 68 d 



IOBBBI q 



sp x -g_ 



re 5 



ill 



re 



A .J. 



0 treo 



in 



T kGate ; Memory main. ram . ram 



Memory Viewer Page: 




00 : 5c 01 4c 4c 36 00 Set 00 33 00 ff xx xx xx xx xx 

10 : XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX 

20 : XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX 

: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX 



Last Read Access 


Address 
Data 
Time 


04 

8Ti36 

2,50855ms 



Last Write Access 


Address 
Data 
Time 





« 



9.11 Version "B2" 

Here is described a further modification to the simple CPU, in order to slightly im- 
prove its efficiency through a direct connection between the RAM module and the IR 
register, so that an opcode can be transferred from the memory to the instruction reg- 
ister without interfering with the data bus. 



Version "B": optimization 



499 



Figure 9.30. Simple CPU, version "B2". 

control bus 



96 
/ 



reset 



• off 



*e r R 



I 



f CTRL , 

c 



> ft 



A 2 A 



D C 

IR 



1+ I* 1+ 



SP x 

C D c 



c P J C 
s RAM 



1+ h It 1+ 



D C 
B o 



B i 



J* 



i+ a h 



^9 5 



D C 

J^xMDR 

B o 



1+ 1$ 1+ 



B i 



/ 2 



4.8 



a C 


b 


SEL 


F 


t B 


0 



B i 



B xf 8 FL x^fo ALU h 



8 + 



□ C 



A x 

C D c 



/' 5 



A S K C 

TTY 

B oO 01 



Ti 



data bus 



o B i 

IOA x 

C D c 



/ 2 



^8 



/ 2 



To make the connection shown in the figure, the RAM module is modified, in order to 
drive an auxiliary output (X); consequently, it enlarges its connection to the control 
bus, forcing to readapt the connections of the other modules. 



500 Version "B": optimization 

Figure 9.31. Module RAM modified with the addition of the auxiliary output. 



CO = br (bus read) 
C1 = bw (bus write) 
5 C2 = xw (extra write) 
C4:3 = index selection 



clock 



P = register PC 
I = register I 
J = register J 
S = register SP 



p>- 

l> 8- 



J> 7f~ 



S> 7^ 



c>" 



index_register 



1+ V dd 



p 
H 

c 



□ 



bus read 



- address 



extra_write 



bus_write 



-O B 



-> X 



V 
o 

The fields declaration of the control word requires a change of meaning of the con- 
trol lines on the RAM module, together with the shift on the connection of the other 
modules: 



field 


Ctrl [1:0] 


= {nop=0, stop 


=1, load=2 } ; 


field 


pc [ 6 : 2 ] 


= {br=l, bw=2, 


xr=4, inc=8, dec=16}; 


field 


sel[10:7] = 


= {if_carry=l, 


if_not_carry=3, 






if_zero=5 , 


if_not_zero=7 , 






if_negative 


=9, if_not_negative=ll , 






if_overf low 


=13, if_not_overf low=15 } ; 


field 


mdr[15:ll] = 


= {br=l, bw=2, 


xr=4, inc=8, dec=16}; 


field 


j[20:16] 


= {br=l, bw=2, 


xr=4, inc=8, dec=16}; 


field 


ram[25:21] = 


= {br=l, bw=2 , 


xw=4 , p=0, i=8, j=16, s=24 } ; 


field 


ir[30:26] = 


= {br=l, bw=2, 


xr=4, inc=8, dec=16}; 


field 


sp[35:31] = 


= {br=l, bw=2, 


xr=4, inc=8, dec=16}; 



Version "B": optimization 



501 



field 


i [ 4 0 : 3 6 ] 


= (br=l, 


bw=2, xr=4, inc=8, dec=16}; 


riela 


b L 4b : 4 1 J 


r i_ _ _ -1 

= {br=l, 


bw=z, xr=4, inc=o, dec=16}; 


riela 


r 1 L b U : 4 6 J 


= {br=l, 


bw=z, xr=4, mc=o, dec=16}; 


riela 


alu [ bb : b 1 J 


= {not=l 


, and=j, or=o, xor= /, lsnl = y, lsnr=ll, 






asnl = 


13, asnr=15, rotl=17, rotr=19, rotcl=21, 






rot cr 


=2 3, add_c=2b, sub_b=2 7, add=2y, sub=31}; 


r leia 


a L o U : b o J 


- {br-1, 


bw=2, xr=4, mc=8, dec=16}; 


field 


ioa [ 6b : 61 ] 


= {br=l, 


bw=2, xr=4, inc=8, dec=16}; 


field 


ioc [69:66] 


= {br=l, 


bw=2, req=4, isack=8}; 



The difference inside the microcode declaration, is due to the fact that the RAM must 
have enabled the line xr to be able to communicate with the IR register, therefore, all 
the microinstruction for the fetch should be changed in the following way: 

ir=br ram=xw ram=p pc=inc ctrl=load; 



Finally, where possible, the fetch microinstruction that appears at the end of each 
macroinstruction procedure, is merged with the penultimate microinstruction. It is 
possible precisely with the instructions for copying a value from one register to an- 
other and those that do something with the ALU: 



rav 


_mdr_a : 








a=br mdr=bw 


ir=br ram=xw ram= 


: p pc=inc ctrl=load; 


mv 


_mdr_b : 








b=br mdr=bw 


ir=br ram=xw ram= 


: p pc=inc ctrl=load; 


mv 










i=br j=bw ir 


=br ram=xw ram=p 


pc=inc ctrl=load; 


mv 


_ j_mdr : 








mdr=br j=bw 


ir=br rara=xw ram= 


: p pc=inc ctrl=load; 



not : 






















a=br 


alu 


=not 


f l=xr 


ir=br 


ram=xw ram=p 


pc=inc 


Ctrl 


=load; 


and : 






















a=br 


alu 


=and 


f l=xr 


ir=br 


ram=xw ram=p 


pc=inc 


Ctrl 


=load; 



502 



Version "B": optimization 



add : 






















a=br 


alu 


=add 


f l=xr 


ir=br 


ram=xw ram=p 


pc=inc 


ctrl 


=load; 


sub : 






















a=br 


alu 


=sub 


f l=xr 


ir=br 


ram=xw ram=p 


pc=inc 


Ctrl 


=load; 



503 

Version "C": 16-bit little-endian 



Chapter 10 



10.1 General purpose 16-bit registers 505 

10.2 Module "BUS" 508 

10.3 Module "ALU" 509 

10.4 Module "SEL" 518 

10.5 Module "RAM" 519 

10.6 Module "IRQ" 521 

10.7 Module "IVT" 529 

10.8 Module "CTRL" 531 

10.9 Opcodes 534 

10.10 Microcode 558 

10.11 Interrupts management 578 

10.12 Module "RTC": real time clock 580 

10.13 Module "TTY" 581 

10.14 Module "HDD" 586 

10.15 Macrocode: terminal usage example, through interrupts 592 



Here is a further extension of the project with 16-bit registers, while continuing to 
manage a memory organized in 8 -bit words. Since the TKGate microcode-macrocode 
compiler stores the 16-bit values by reversing the order of the bytes (or at least it does 
in the version compiled for x86 architecture), this version of the CPU (which is now 
a computer with devices) is organized in little-endian mode. 



Attachments 


Description 


attachments/xcpu/xcpu-c. v 


TKGate Verilog netlist source file. 


attachments/xcpu/xcpu-c.gm 


TKGate microcode and macrocode source 
file. 


attachments/xcpu/xcpu-c-terminal.vpd. 
tcl 


TCL/Tk script related to the terminal mod- 
ule TTY. 



504 



Version "C": 



16-bit little-endian 



Figure 10.2. Simple CPU version "C". 




irq_signal 



Among the other new things, in the figure should be observed the presence of the 



Version "C": 16-bit little-endian 



505 



BP register {base pointer) whose purpose is to facilitate the use of the stack of data 
when performing function calls. The register should be used in a manner similar to 
the 8086-8088 calling conventions; otherwise, the same register is known with the 
name "FP" {frame pointer). 

10.1 General purpose 16-bit registers 

The registers of this version of the project have a 16-bit size, but are divided into two 
bytes, the contents of which can be accessed separately. Furthermore, it is possible to 
increase and reduce the value of these registers, of one or two units. 

Figure 10.3. 16-bit registers: external appearance. 

K bus read {load) I 

b\ bus write \ 

b 2 auxiliary bus (read/write) i 

h select byte BO: 7:0 \ 

h select byte Bl: 15:8 \ 

h plus 1 (register+—l) \ 

b 6 plus 2 (registers -2) I 

b 7 minus 1 (register--!) \ 

b% minus 2 (register- -2) \ 



bn" b 0 register content copy 



b 0 clear 
h clock 




test point: active when the register 
is loading a value from the main 
bus (B) or from the auxiliary bus (X) 




test point: active when the register is 
writing a value to the main bus (B) 
or to the auxiliary bus (X) 



})..}) auxiliary bus connection 



b\5" b Q main bus connection 



506 



Version "C": 16-bit little-endian 



Figure 10.4. 16-bit registers: internal structure. 




Version "C": 16-bit little-endian 
Figure 10.5. Modules H8 and L8. 



507 




The module byteselect contained inside the 16-bit registers, is used to reduce the 
reading of the contents of the register to only 8 bits, choosing from the least significant 
byte or the more significant one. For example, if the register value is ABCDi 6 and the 



508 



Version "C": 16-bit little-endian 



least significant byte is selected, the value 00CDi 6 is obtained; on the other hand, if 
the more significant byte is selected, the value 00ABi 6 is obtained. 

When a value is to be written inside the register, the separate modules H8 and L8 can 
load independently. If a single byte is to be written, to the most significant position 
inside the register (without modifying the least significant one), the input from the 
bus is swapped by the module byteswap and the H8 loads alone. 

Figure 10.6. Modules byteswap and byteselect. 



BYTESWAP 



Hi 

V 



Li 

V 



/' 8 




Hi 
V 



v 

Ho 



v 

Lo 



[of-JiujJl* 



D 



V 

Ho 



-< high 



-<lo 



v 

Lo 



« 



10.2 Module "BUS" 

For this version of the project there is a new module that allows to the control unit to 
write a value to the data bus. The module can select the main bus (B) or the auxiliary 
bus (X). 



Version "C": 16-bit little-endian 



509 



Figure 10.7. Module BUS. 




10.3 Module "ALU' 



18 



aux 



17 



16 



15:0 



bus write 



demux 



/ 



6/ X N6 



0 



X B 



V, 



dd 



« 



The ALU unit is redesigned from the previous version of the project. Currently is it 
able to handle 16-bit values and some more functions. It should be noticed that there 
are separated flags for 8 -bit and 16-bit operations. 



510 



Version "C": 16-bit little-endian 



Figure 10.8. ALU overall structure. 




Version "C": 16-bit little-endian 



511 



Figure 10.9. Login unit inside the ALU. 



A 



B 



C LOGIC 



Q 



C=0: 


q = 


a 


C=1: 


q = 


a AND B 


C=2: 


q = 


aORb 


C=3: 


q = 


aXORb 


C=4: 


q = 


NOT (a XOR b) 


C=5: 


q = 


NOT (a OR b) 


C=6: 


q = 


NOT (a AND b) 


C=7: 


q = 


NOT a 





v 

Q 



512 



Version "C": 16-bit little-endian 



Figure 10.10. Module AS: addition and subtraction. 



carry out 
borrow out 



carry in 
borrow in 




Co16 016 



Co8 08 



Version "C": 16-bit little-endian 



513 



Figure 10.11. Module FAS (full adder-subtractor) that is found inside the arith- 
metic unit. The fa are just standard full adders. 



0 



/a 




h-tomTtcooj-T-o 




v 

s 



514 



Version "C": 16-bit little-endian 



Figure 10.12. Module SH, used for bit shift and rotation with carry. 



C A 
Co16 

016 SH a 

Co8 

08 s 



16 



0 



0 



V 

Co16 



V 

016 



Ir 


A 


la 


lin 




rout 


lout 


sh 


nn 


CI 




Cr 


0 


S 





arithmetic 



0 



right 



Ir 


A 


la 






lin 




rout 






lout 


sh 








nn 






CI 

0 


S 


Cr 


■* 


r 



sh_left_and_carry_ 



v 

s 



V 

08 



use_previous_carry 



-<Ci 



sh_right_and_carry_right 



V 



V 

Co8 



4 



-<C 



Version "C": 16-bit little-endian 

Figure 10.13. Module ROT: rotation without carry. 




A 

V 



I 1 

oo o 

ID 



/B 



n 



right 



lr 


A 


la 


lin 




rout 


lout 


sh 




nn 


CI 




Cr 


0 


S 





lin 

lout 

CI 



sh 



la 



rout 



Cr 



S 



516 



Version "C": 16-bit little-endian 



Figure 10.14. Module sh used inside the shift and rotation modules. 



0=left 
1 =right 



lin>- 

leftin 



lout < 

left out 



carry 
lato 
sinistra ci 



0=logic shift 
1=arithmetic shift 



/8 



[3] 



[1] 



[3] 



[3] 



[4] 



[2] 



overflow 



^ rout 

right out 

— <rin 

right in 



0 



carry 
lato 
cr destro 



[1] Controllo della rotazione aritmetica: 

- lo scorrimento deve essere aritmetico; 

- deve trattarsi di scorrimento a destra; 

- il bit piu significativo deve essere a uno. 
[2] Controllo dello straripamento: 

- lo scorrimento deve essere aritmetico; 

- il bit piu significativo non deve essere cambiato. 
[3] Collegamento alia cifra piu significativa o di segno. 
[4] Collegamento alia cifra meno significativa. 
[CI] Riporto lato sinistra: 

- lo scorrimento e verso sinistra; 

- la cifra piu significativa era 1 . 
[Cr] Riporto lato destro: 

- lo scorrimento e verso destra; 

- la cifra meno significativa era 1 . 

The current ALU is able to modify the flags through the FAS module (flags add- 
subtract). As already pointed out, there is a couple of flags, to distinguish between 
8 -bit and 16-bit results. For example there is a 8 -bit carry and another 16-bit carry. 
When the flags are modified through the FAS module, both flags are changed; that is, 
if the carry flag is changed, this modification is applied to both 8 -bit and 16-bit carry 
flags. The fas module receives a 8 -bit mask and the function to be applied (bitwise 
AND or bitwise OR), to change the flags status. 



Version "C": 16-bit little-endian 



517 



Figure 10.15. Module fsr: direct flags status change. 





/ 


'16 




/ 


'16 




1 




0 







V 



Fo 



The module SHORFILL is used inside the ALU to reduce the size of a result: if the size 
reduction is requested, then the most significant byte is filled. If the value is unsigned 
or positive, the most significant byte is zeroed, otherwise is set to all ones, to extend 
the sign (if no size reduction is requested, no modification is applied). 



518 



Version "C": 16-bit little-endian 



Figure 10.16. Module shortfill, for size reduction. 



SHORTFILL 



O 



size 



sign 



□ 



« 



i 

v 



/16 



I I 

00 o 

in 



v 

o 



_J 



V 



~<SIZ 



-sign 



10.4 Module "SEL" 

The SEL module is extended to handle the distinguished register sets, for eight or 
sixteen bits. There is also a new flag used to enable hardware interrupts (IRQ), but 
there are not branch conditions related to the interrupt flag status; that is why the SEL 
module just ignores the interrupt flag. 



Version "C": 16-bit little-endian 



519 



Figure 10.17. Module SEL. 




control 

CO = bus write 
C3:1 =func 



c = 


01 


if carry 8-bit 


c = 


03 


if not carry 8-bit 


c = 


05 


if zero 8-bit 


c = 


07 


if not zero 8-bit 


c = 


09 


if negative 8-bit 


c = 


11 


if not negative 8-bit 


c = 


13 


if overflow 8-bit 


c = 


15 


if not overflow 8-bit 


c = 


17 


if carry 1 6-bit 


c = 


09 


if not carry 1 6-bit 


c = 


21 


if zero 1 6-bit 


c = 


23 


if not zero 1 6-bit 


c = 


25 


if negative 1 6-bit 


c = 


27 


if not negative 1 6-bit 


c = 


29 


if overflow 1 6-bit 


c = 


31 


if not overflow 1 6-bit 



bO = carry 8-bit 
b1 = zero 8-bit 
b2 = negative 8-bit 
b3 = overflow 8-bit 
b4 = interrupt enable 

b8 = carry 16-bit 
b9 = zero 16-bit 
b1 0 = negative 1 6-bit 
b1 1 = overflow 1 6-bit 
b12 = interrupt enable 




bus write = select 

10.5 Module "RAM" 

The RAM memory continues to be organized in 8 -bit words, as it happens for com- 
mon architectures. To read or write a 16-bit value, it is necessary to access two times: 
as the architecture is little-endian, read and write start always from the least significant 
byte. 



520 



Version "C": 16-bit little-endian 



Figure 10.18. Module RAM. 



S J I P 

V V V V 



P = register PC 
I = register I 
J = register J 
S = register SP 



index_register 




control 



-<c 



CO = load (bus read) 
C1 = bw (bus write) 
C2 = aux (auxiliary bus) 
C4:3 = index selection 



The RAM module contains DH16 that is a register that repeats on the Q output the value 
received form the D input, as long as the input H is negated (active, as the meaning 
of the line is complemented): when the input line H is asserted (hold), the output Q 
is freezed. 



Version "C": 16-bit little-endian 



521 



p >- 

s>- 

E>- 
R>- 

C >- 



Figure 10.19. From left to right the steps to build DH/z modules: it all starts from a 
SR latch with enable input; than it becomes a D latch and finally these D latch are 
put together in paralel. Obviously, the module DH16 is made with two modules 
DH8, which is made with two modules, DH4. 



module «e» module «DH1> 



D 

V 

/4 



O 1 



c >- 

H >- 



module «DH2» 



e E » 
" 5 C R 7 



D P 
DH1 q 

H ft 



module «DH4> 



■D P 

DH1 q- 



D f 

DH2 q 
H r 



D P 
DH2 q 



/2 



10.6 Module "IRQ" 

This version of the simple CPU handles interrupts, distinguishing between those pro- 
duced internally by the CPU itself, those generated by external devices and those 
managed by software. The IRQ module is responsible to collect hardware interrupts 
from the devices, to sort interrupts by a priority, to supply the selected interrupt to 
the control circuit that must then do something with it. In short, the module receives 
IRQ interrupts asynchronously, it stores and determines which is the interruption to 
be served first. The module appears externally as if it were a register, since it must be 
able to receive an interrupt mask and the same mask can be read from the module. 



« 



522 



Version "C": 16-bit little-endian 



Figure 10.20. Module IRQ: full schema. 

■ irq_clear - 



irq_register 




0000— > 0100 
0001 — > 0100 
0010— > 0101 
0100— > 0110 
1000— > 0111 





Is 


B 




Q 


IRQ 


In 


C 


IRQ 


c 


t 


t 


t 



interrupt 



| o" 


number 


2 


In 


3 

r- 



hardware interrupt: 01.. 



To understand what really does the IRQ module, it is necessary to analyze its compo- 
nents, with the help of a block diagram, shown on the next picture. 



Version "C": 16-bit little-endian 



523 



Figure 10.21. Block diagram for the IRQ module. 



IRQ 





interrupt 
number 



bus dati 

It is simpler to start from the analysis of the register that contains the IRQ mask, 
which is located at the bottom left of the overall scheme: it is a 4-bit register (one for 
each IRQ) which reads data from the bus to update its value and writes to the data bus 
to allow to know the value that it contains. 



524 



Version "C": 16-bit little-endian 



Figure 10.22. IRQ mask detail. 

IRQ register 



irq_mask_register 



Ck 



D 

DR4 L 



Q 



12 



en 

i i 



/ 16 



clear 



clock 



load 



4 I \ 4 / 



IRQ priority 



clear o 
1 



bus write 



■<c 



0 

B 

The DR4 module is a 4-bit register, made of D flip-flops, through the following steps. 
Figure 10.23. Building DRn modules. 



module «DR1» 



Q -S- 



module «DR2» 



module «DR4» "// 



-<L 



Q 


P 


D 


Q 


C 


Ck 



-<Ck 



C >- 



DR1 L 



DR1 L 



-<L 



Ck>- 



C >- 



DR2 L 



DR2 L 



-<L 



A 
c 



wo 
I I 



Version "C": 16-bit little-endian 



525 



In the upper left of the overall scheme, it appears the IRQ register, whose purpose is to 
store the hardware interrupts received from the input IRQ. this register is constructed 
in an unusual way, because it is made by D flip-flops, positive edge, but the D inputs 
of these flip-flops is connected so as to be always active, while the clock input is used 
to receive the IRQ signal. In practice, a IRQ signal arriving at the flip-flop clock line, 
activates permanently the flip-flop. The IRQ register flip-flops can be reset to zero 
only asserting the input line C. 

Figure 10.24. Received IRQ register. 

IRQ 

V 



D 
Ck ' 



D <- 

Ck <r 



Q 
Q 



irq clear 



4 



Q <" 



/' 4 



IRQ priority 



IRQ mask 

The value stored inside the IRQ register and the value from the IRQ mask below, are 
compared with a multiple AND gate (a separate gate for each IRQ line) and then given 
to a module that selects one IRQ line according to a priority: the lowest IRQ number 
requested is chosen. The module responsible for the priority selection communicates 
with an encoder that takes care of transforming the IRQ chosen into a number of 
interruption: IRQO becomes INT4, IRQ1 becomes INT5, up to IRQ3 which becomes 
INT7. It should be observed that the priority selection module emits a signal (irq_set) 
about the actual presence of an IRQ that needs to be served, because the absence of 
an IRQ produces anyway the value INT4 through the encoder. 



526 



Version "C": 16-bit little-endian 



Figure 10.25. Priority selection and encoder. 



IRQ clear register 



IRQ register 



IRQ mask 



irq_priority 



priority_0 



priority_2 



priority_3 



ls irq_set 



> Is 



irqjojnt 



0000— > 0100 
0001 — > 0100 
0010— > 0101 
0100— > 0110 
1000— > 0111 



t 



interrupt 
number 



In 



hardware interrupt: 01 . 



When an IRQ has been served, there is the need to reset the matching D flip-flop in 
the IRQ register (top left). To obtain this result a reset register is used (it appears at 
the top right). The reset register is made of D flip-flops (positive edge) which under 
normal conditions (when the input irqjione is zero) produce at their output a value 
equal to one, since they are initialized to one (input P to zero). The output of the 
reset register is connected to the C input of the IRQ register: as long as the C lines 
of the IRQ register are negated (in that case it means that the lines are active), the 
IRQ register retains its stored value. However, when the reset register receives the 
signal irqjione it gets and store the complemented IRQ (selected by the priority); 
that is: the last selected IRQ becomes zero inside the reset register and then, asserts 
the matching C input line of the IRQ register, resetting it. At that point, the priority 
module might select a new IRQ requesting to be served. 



Version "C": 16-bit little-endian 



527 



Figure 10.26. Served IRQ reset register. 



so 

as 



clear 



Q Q 

G P 

Ck D 

It |t_ 



Q Q 

C P 
Ck D 



Jt Lt- 



Q Q 

C P 
Ck D 



l±_ 



Q Q 
C P 
Ck D 



Jt \±_ 



clock 



clear 



2 

/ 



-<c 



/A 



/A 



IRQ priority 



irq_done 



3 



-<C 



The C inputs at the IRQ register on the left are not connected directly to the served 
IRQ reset register, because it might be necessary to reset the whole IRQ register, 
through the control reset line. For this reason, there is an AND gate to handle that 
situation. 



The served IRQ reset register might be designed in a more compact way, as the fol- 
lowing picture shows. 



528 



Version "C": 16-bit little-endian 



Figure 10.27. served IRQ reset register, made of a module D4. 
irq_clear 




The module Dn is made of D flip-flops, in paralel, as the following figure shows. 



Version "C": 16-bit little-endian 



529 



Figure 10.28. Building Dn modules. 



module Dl 
(Dflip-flop) 



Ck> 



C > 




<Ck 



10.7 Module "I VT" 

In order to manage interruptions (CPU, hardware and software), this version of the 
simple CPU needs to have a IVT table (interrupt vector table), which resides in RAM 
memory. The table IVT must be implemented as an array of 16-bit integers (little- 
endian), each of which represents the address of a routine to execute when the match- 
ing interrupt is enabled. Therefore, IVT[n] must match the address of the routine that 
has to perform the activity requested by the interrupt n . 

The module IVT is used to store the location of the IVT table, which is precisely the 
location of IVT[0]. The module receives the number of a certain interruption from 
two independent inputs; such interrupt number is then transformed into the matching 
address in memory that contains the reference to the requested routine to be started. 



« 



530 



Version "C": 16-bit little-endian 



Figure 10.29. Module ivt. 





t 


4- 


c 


D 


C 


la 


IVT 


lb 


i 


B 


0 




* 





2 
/ 



IVT_start_address 



clock 



clear 



J? 



Ck 



DR16 

Q 



la 

V 



lb 

V 



0 1 



interrupt_select 



r 



interrupt 



"1 



16 

interrupt_x_2 



A B 
ADD16 



Co 



Ci 



/16 



-> D 



load 



v- 



bus_write 



-<C 



0 

B 



v v 



V v 

i o 



Inside the ivt module there is a register represented by the module DR16. The module 
DR16 is used to store the IVT table starting address. The module DR16 is made in the 
same manner already described for the module DR4, inside the previous section. The 
module ADD16 is made of sixteen full adders, connected in parallel with a cascade 
carry. Even the ADD16 module is made through different stages, as it is for DR16. 



Version "C": 16-bit little-endian 



531 



Figure 10.30. Building modules ADDw. 




3 Y 



"<Ci CO <r-+ 



A B 

ADD2 

Co 



Ci 



B 

V 

\- 



— _ ADD2 „. 
«- Co Ci 



S 



00 



■3 



A 

V 



"<Ci Co 



B 

V 



/ 1 



A B 




A B 


ADD4 _. 

Co Ci 




ADD4 
Co Ci 


s 




S 


1+ 







-<Ci 



10.8 Module "CTRL" 

The module CTRL has only minor changes from the previous version: the opcode oc- 
cupy only eight bits (input /), the microprogram counter (MPC) is reduced to only nine 
bits, because the microcode does not exceed 512 lines, the microcode word requires 
many more bits, so, five memory modules are used together to drive a control bus of 
160 bits. The input to the microprogram counter is mediated by a multiplexer that per- 
mits to enter an address when the D flip-flop on the right is active. This address must 
match the point where the microcode describes the steps required to serve a hardware 
interrupt (IRQ); in practice, such address must match the irq label placement, as it 
can be determined from the files produced by the TKGate compiler. 



« 



532 



Version "C": 16-bit little-endian 




Version "C": 16-bit little-endian 



533 



Figure 10.32. Control unit detail. 



V 

map 



Microcode Symbols 

iret 00000169 
irq 0000016e 



ivtl 



00000180 



9 



irq: 16E 



0 1 



clock pulse 



clock 



clock 



7 


Q 


P 


D 




+■ 








Q 


C 


Ck 



interrupt set 





D 




Clk 










MPC 


L 


Clr 










Q 





clear 



nicn 



clear 



mic o0 



> 




> 




> 




> 




> 


81 

o 




81 

a 




81 

o 




81 

a 




81 

D 



/ 32 



clear 



clock 
clear 



flag IRQ enable 



modulo IRQ 



/ 160 



V 

c 

Looking at the figure above, it is important to clarify what happens when a hardware 
interrupt is received: the IRQ module, as described in section 10.6, sends to the ivt 
module the interrupt number matching the selected IRQ to be served; then, the IRQ 
module activates the Is output (interrupt set). The interrupt-set line activated by the 
IRQ module, reaches the control unit only if the interrupt-enable flag (/) is active. 
When the interrupt request reaches the module CTRL at the input Is , it is stored into 
the D flip-flop (positive edge) that appears in the upper right of the diagram; then, 



534 



Version "C": 16-bit little-endian 



at the first occasion in which the control unit must read a new opcode, it is instead 
directed to execute the instructions matching the label irq. 



Listing 10.33. Memory banks declaration. 


m 3 7*^1 V^i 3 n V r / •01 
lLLci|J JJcLIlJV [ / . U J 


/~* ~\~ v 1 m ^ ir\ • 
L U -L _L • ILLd-J^ f 


irn p rnrriHp V^i ^ ti V 1" X 1 •01 

ILL _l_ LI U CL11JV [vJ_L • U J 


r~i ~\~ "Y~ 1 TY1 1 r^T~oO* 
LL-J — L • ILL _l_ LI \J \J f 


microcode bank [63: 32] 


Ctrl . microl ; 


microcode bank [95: 64] 


Ctrl . micro2 ; 


microcode bank [127: 96] 


Ctrl . micro3 ; 


microcode bank [ 15 9 : 12 8 ] 


Ctrl . micro4 ; 


macrocode bank [15:0] 


ram . ram; 



10.9 Opcodes 

The opcode size used in this version of the simple CPU, remains limited to eight bits, 
but instead of using just a sequential number to distinguish them, the opcodes are now 
structured with a criterion. First there is a definition used to convert register names to 
integer numbers, so that three bits are requested to distinguish them: 

registers 1=0, J=l, A=2, B=3, BP=4, SP=5, MDR=6, FL=7; 



There are different kind of operands; the simplest cases are declared at the beginning: 



operands 


op_0 { 


}; 


{ I; 


operands 


op_8 { 


#1 = 


{ +1=#1[7:0]; }; 


}; 

operands 


op_l 6 { 


#1 = 

}; 


{ +1=#1[7:0]; +2=#1[15:8]; }; 



It is understood that op_0 means the request of no operand at all; that op_8 requires 
an 8-bit operand; that op_16 requires a 16-bit operand. For the 16-bit operand it is 
requested to read two separate bytes, starting from the least significant one, because 



Version "C": 16-bit little-endian 

the byte order organization is little-endian. 
Listing 10.36. Opcodes declaration. 



535 



op nop { 


















map nop: 


0x00; 


// 


not operate 








+0 [7 : 0] =0x00; 


















operands op_0; 

}; 


















op mv { 




// 


00 


zz 


mv 








map nop: 


0x00; 


// 


00000000 


zz 


mv 


%I 


%I not 


valid => nop 


map mv_i_j : 


0x01; 


// 


00000001 


= 


mv 


%I 


%J 




map mv_i_a : 


0x02; 


// 


00000010 


zz 


mv 


%I 


%A 




map mv_i_b : 


0x03; 


// 


00000011 


= 


mv 


%I 


%B 




map mv_i_bp : 


0x04; 


// 


00000100 


zz 


mv 


%I 


%BP 




map mv_i_sp : 


0x05; 


// 


00000101 


= 


mv 


%I 


%SP 




map mv_i_mdr : 


0x06; 


// 


00000110 


= 


mv 


%I 


%MDR 




map mv_i_f 1 : 


0x07; 


// 


00000111 


zz 


mv 


%I 


%FL 




map mv_ j_i : 


0x08; 


// 


00001000 


= 


mv 


%J 


%I 




map op_error: 


0x09; 


// 


00001001 


zz 


mv 


%J 


%J not 


valid 


map mv_ j_a : 


OxOA; 


// 


00001010 


= 


mv 


%J 


%A 




map mv_ j_b : 


OxOB; 


// 


00001011 


zz 


mv 


%J 


%B 




map mv_ j_bp : 


OxOC; 


// 


00001100 


= 


mv 


%J 


%BP 




map mv_ j_sp : 


OxOD; 


// 


00001101 


= 


mv 


%J 


%SP 




map mv_ j_mdr : 


OxOE; 


// 


00001110 


= 


mv 


%J 


%MDR 




map mv_j_f 1 : 


OxOF; 


// 


00001111 


zz 


mv 


%J 


%FL 




map mv_a_i : 


0x10; 


// 


00010000 


= 


mv 


%A 


%I 




map mv_a_j : 


0x11; 


// 


00010001 


zz 


mv 


%A 


%J 




map op_error: 


0x12; 


// 


00010010 


zz 


mv 


%A 


%A not 


valid 


map mv_a_b : 


0x13; 


// 


00010011 


= 


mv 


%A 


%B 




map mv_a_bp : 


0x14; 


// 


00010100 


zz 


mv 


%A 


%BP 




map mv_a_sp : 


0x15; 


// 


00010101 




mv 


%A 


%SP 




map mv_a_mdr : 


0x16; 


// 


00010110 




mv 


%A 


%MDR 




map mv_a_f 1 : 


0x17 ; 


// 


00010111 




mv 


%A 


%FL 




map mv_b_i : 


0x18; 


// 


00011000 




mv 


%B 


%I 




map mv_b_j : 


0x19; 


// 


00011001 




mv 


%B 


%J 




map mv_b_a : 


OxlA; 


// 


00011010 




mv 


%B 


%A 




map op_error: 


OxlB; 


// 


00011011 




mv 


%B 


%B not 


valid 



536 



Version "C": 16-bit little-endian 



map 


YY1 x T r*\ r*\ "V\ • 

mv D Dp . 


UX1L, 


// 


/inn 7 17 /in 
UUUJ.J.J. UU 




mv 






map 


mv d sp . 


u X ± JJ , 


// 


nnn i i i m 

u U U J. ± J. U 1 




mv 


"6X3 SiSlr 




map 


YY1 T 7" r*\ TYl "V* ■ 

mv d ma it . 


UXlh, 


// 


nnn i i i i n 

UUU J. 1 1 1U 




mv 


S-T3 5-1MT1D 




map 


TYl T 7" V"\ ~F I • 

mv d r _l . 


n V 1 p • 


/ / 


nnn 11111 

UUU J. -Z.-Z.-Z.-Z. 




mv 


sd se ±1 




map 


TYl "V 7" r*\ ~V~\ ~1 • 

mv op 1 . 


uxzu, 


// 


007 nnnnn 
UU J. uuuuu 




mv 


S DC Si 




map 


mv bp "2 • 


n v 9i • 

UXZl, 


// 


nni nnnn 1 
UUJ. uuuu± 




mv 


9-J3D & T 




map 


TYl "V 7" U~\ — s ■ 

mv Dp a . 


UXZZ , 


// 


nni nnn 1 n 

UUJ. UUU J. u 




mv 


9-T2TD 9r 7i 




map 


mv Dp D . 


UXZ J, 


/ / 


nni nnn 1 1 

UUJ. UUU J. J. 




mv 


SOe SO 




map 


op error : 


UXZ1, 


// 


nni nn 1 nn 

UUJ. UUJ. UU 




mv 


'Sof sof nou 


valid 


map 


TYl T 7" Y\ "V~\ Cy "V~\ • 

mv Dp sp . 


n v 9 r ■ 

UXZ J, 




nni nn 1 ni 

UUJ. UUJ. UJ. 




mv 


SDc SiSir 




map 


TYl T T V"~\ Y~\ TYl /""N "V* • 

mv pp mur . 


UXZO, 




nni nn 1 1 n 

UUJ. UUJ. ± U 




mv 


SBr T>JXUJ£\ 




map 


TYl T 7" V\T~\ -4— I » 

mv Dp r _i_ . 


UXZ/, 


/ / 


nni nn 111 

UUJ. UUJ. J. J. 




mv 


SDtr SC Jj 




map 


mv sp i ; 


UXzo, 


// 


nni ni nnn 
uu± u± UUU 




mv 


0, CUD 3- T 

for ?1 




map 


mv sp j '. 


uxzy, 


// 


nni ni nni 

UUJ. UJ. UUJ. 




mv 


a. CD 3r T 




map 


TYl T 7" fl "V~\ — 1 • 

mv sp a . 


UXZA, 


/ / 


nni ni ni n 

UUJ. UJ. U J. u 




mv 


for -e/i 




map 


TYl X 7" f"1 "V~\ V~\ • 

mv sp d . 


U XZ Jd , 


// 


nni ni ni 1 

UUJ. U± UJ.J. 




mv 


9. CD 3-D 




map 


TYl X 7" t — 1 ~V"N * 

mv sp Dp . 




// 


nni ni 1 nn 
uu± u±± UU 




mv 


9-CD &CD 




map 


op error : 


U XZ JJ , 


// 


nni ni 1 ni 

UUJ. UJ. J. UJ. 




mv 


¥or SOf nOZ. 


valid 


map 


TYl "V 7" I— 1 Y—\ TYl / — *J "V* ■ 

mv sp mar . 


uxzhi, 


// 


nni ni 1 in 

UU1U111U 




mv 


0, GT3 Q- Ayfn D 
SOtr SJXLUri 




map 


TYl X 7" fl V~N ~T~ 1 • 

mv sp ii . 


UXZr , 


// 


nni ni 1 1 1 

UUJ. UJ. xxx 




mv 


Q. CD S-IPT 

sof sn Jj 




map 


TYl "V 7" TYl "V* ^ * 

mv mar i . 


n v "5 n • 


// 


nni 1 nnnn 
uu±± uuuu 




mv 


SMJJK. SI 




map 


TYl "V 7" TYl "V* — 1 * 

mv mar j . 


UXjl, 


// 


nni 1 nnn 1 

UUJ. J. UUU J. 




mv 


sjyuJK. su 




map 


TYl T 7" TYl /^N "V* — 1 ■ 

mv mar a . 


UXjZ, 


/ / 


nni 1 nn 1 n 

UUJ. J. UUJ. U 




mv 


SvdUts. SA 




map 


TYl T T TYl /""N "V^ V"\ • 

mv mar d . 


UXjj, 


/ / 


nni 1 nn 1 1 

UU XX UU 1 1 




mv 


snouts, so 




map 


TYl "V 7" TYl ■ 

mv mar Dp . 


n v "5 a • 

UXj^l , 


// 


nni 1 ni nn 
uu±± u X UU 




mv 


%MDR %BP 




map 


mv mdr sp : 


uxjo; 


// 


nni 1 ni ni 
UU11U1 Ul 




mv 


%MDR %SP 




map 


op error : 


n ^ "3 £ • 


// 


nni 1 ni in 

UU11U11U 




mv 


%MDR %MDR not valid 


map 


TYl X 7" TYl S~*l "V* ~T~ 1 • 

mv mar r_i_ . 


UXj / , 


// 


nni 1 ni 1 1 

UUJ. x UJ. x x 




mv 


%MDR %FL 




map 


mv f 1 i '. 


UXJO, 


// 


nni 1 1 nnn 
uum uuu 




mv 


%FL %I 




map 


mv f 1 ~] i 


uxjy, 


// 


nni 1 1 nni 
uum uu± 




mv 


%FL %J 




map 


mv f 1 a '. 


UXjA, 


// 


nni 1 1 ni n 
uum ui u 




mv 


%FL %A 




map 


TYl X 7" ~T~ \ V~\ • 

ITLV r _L D . 


U XoJd , 


// 


nni 1 1 ni 1 
uum uxj. 




mv 


%FL %B 




map 


mv f 1 bp : 


UXoL; 


// 


nni 1 1 inn 
U U 111 1 UU 




mv 


%FL %BP 




TYl ^ Yl 


ILL V J L o U . 




// 


nni iiini 

L/ L/ -L -L -L -L L/ -L 




111 V 


%FL %SP 




map 


mv_f l_mdr : 


0x3E; 


// 


00111110 




mv 


%FL %MDR 




map 


op_error : 


0x3F; 


// 


00111111 




mv 


%FL %FL not 


valid 



Version "C": 16-bit little-endian 



537 



+ 0 [7 : 0] =0x00; 








operands { 








%1,%2 = { +0[5:3]=%1; +0[2:0]=%2; }; 

}; 




Op lOdUO 1 


/ / U± UUU± . . 


— ±03.0.0 




map load8_i : 


0x44; // 01000100 


— ±03.0.0 ~6± 




map load8_j : 


0x45; // 01000101 


= load8 %J 




map load8 : 


0x46; // 01000110 


— ±03.00 ft . . . 




map op_error: 


0x47; // 01000111 


= not valid 




+ 0 [7 : 0] =0x44; 








operands { 








(%1) = { +0[1]=0; +0[0]=%1; }; 






#1 = { +0[1] 

}; 


=1; +0[0]=0; +1=#1[7 


: U J ; +Z—w± [ 10 


:8]; }; 


}; 

op loadl6 { 


// 010010. . 


— ±030± O 




map loadl6_i: 


0x48; // 01001000 


— ±O3O±0 ¥1 




map loadl 6_ j : 


0x49; // 01001001 


= lo3dl6 %J 




map loadl6: 


0x4A; // 01001010 


— ±O3O±0 JF . . . 




map op_error: 


0x4B; // 01001011 


= not vslld 




+ 0 [7 : 0] =0x48; 








operands { 








(%1) = { +0[1]=0; +0[0]=%1; }; 






#1 = { +0[1] 

}; 


=1; +0[0]=0; +1=#1[7 


: U J ; +Z—w± [ 10 


:8]; }; 


}; 

op store8 { 


// 010011. . 






map store8_i: 


0x4C; // 01001100 


— score© ! s± 




map store8_j : 


0x4D; // 01001101 


— ex e o ?u 




map store8: 


0x4E; // 01001110 


= storeS #. . . 




map op_error: 


0x4F; // 01001111 


= not vslld 




+ 0 [7 : 0] =0x4C; 








operands { 








(%1) = { +0[1]=0; +0[0]=%1; }; 






#1 = { +0[1] 


=1; +0[0]=0; +1=#1[7 


:0]; +2=#1[15 


:8]; }; 



538 



Version "C": 16-bit little-endian 



1 . 
J > 

\ . 

op storel6 -[ 


// 


m ni nn 
Ul Ul uu . . 




szorei o 




map storel6 1 : 0x50; 


// 


ni ni nnnn 
Ul Ul UUUU 




storei o 


9- T 
Si 


map storero j . uxoi, 


// 


ni ni nnn i 

Ul Ul UUUl 




store 16 


%J 


map stioireit). uxoz , 


// 


ni ni nn i n 

Ul Ul UU 1 u 




store 16 


if • • . 


map op ci i ui . uajj^ 


// 
// 


mm nm i 




not valid 


4-D r i .ni-fivRn- 
+ U L ' . u j -uxou , 












operands { 












(%D = { +0[1]=0; 


+ 0 [0] 


=%1; }; 








#1 = { +0[1]=1; +0[0]=0; +1=#1 [7 

}; 


:0]; +2=#1[15:8]; }; 


}; 

op cp8 *[ 


// 


m ni ni n 
Ul Ul Ul U . 




cpo 




map cp8_ij: 0x54; 


// 


01010100 


= 


cp8 %I 




map cp8 ji: 0x55; 


// 


ni ni ni ni 
Ul Ul Ul Ul 








+ U L / : U J — Uxo 4 ; 












operands { 












(%1) = { +0[0]=%1; 

}; 


}; 










Up Op X O 1 


// 


m m m i 

UJ. U ± UJ. J. . 




cpj. o 




map cpl6_ij: 0x56; 


// 


01010110 




cpl6 %I 




map cpl6_ji: 0x57; 


// 


01010111 




cpl6 %J 




+ 0 [7 : 0] =0x56; 












operands { 












(%D = { +0[0]=%1; 

}; 


}; 










}; 

op return { 


// 


010110. . 








map return: 0x58; 


// 


01011000 




return 




+ 0 [7 : 0] =0x58; 












operands op 0; 

}; 












op call { 


// 


010110. . 








map call: 0x59; 


// 


01011001 




call #. . 





Version "C": 16-bit little-endian 



539 



map can i . 


UXDA, 


// 


mm i m n 

UJ. UJ. J. l/i C/ 


— >~i = 7 7 a T 

— Ca±± ~6± 


ILLcLp L-cL-L-L J . 




// 
// 


ni ni i ni i 

U J. Uii Uii 


— Call ?u 


+ u l ' . u j -uxjo , 










operands { 










#1 = { +0[1]= 


0; +0[0]=1; +1=#1[7 




(%1) = { +0[1]=1; 

}; 


+ 0 [0] 


=%1; }; 




}; 

op int { 










map int : 


U XjL ; 


// 


01011100 


= int #. . . 


xn r 7 • n i — n ^ r r 1 • 
+ u L / . U J -uxot, 










operands op 8; 

}; 










op iret { 










map i ret : 


u xojj ; 


// 


01011101 


= iret 


i n r 7 • n l -nvRn- 
+ u L / . U J — UXDJJ , 










operands op 0; 

}; 










op cleari { 










map clean : 


Pi w IT 1 • 


// 


01011110 


= clear interrupt flag 


+ 0 L / : 0 J = 0xoE ; 










operands op 0; 

}; 










op seti { 










map set i : 


uxoi ; 


// 


01011111 


= set interrupt flag 


+ u L / : u J — uxoi ; 










operanas op u , 

}; 










op ivtl { 










map ivtl: 


0x60; 


// 


01100000 


= load IVT location 


+ 0 [7 : 0] =0x60; 










operands op 16; 

}; 










op j ump { 










map jump: 


0x61; 


// 


01100001 


= jump #. . . 


+ 0 [7 : 0] =0x61; 











540 



Version "C": 16-bit little-endian 



f> T~\ £2i r^nHo /~\ y~\ 1 U • 

(jpti-L d-llU-b (JjJ ± O ^ 

i . 










)' 

op jumpoc i 










map jump8c: 


0x62; 


// 


01100010 


= jump8c #. . . 


+ 0 [7 : 0] =0x62; 










/—\ y~\ £~\ v 3 n H O ati 1 h • 

(JjJt;J_ cLll(J.b (JjJ ± O ^ 

i . 










s> 

op jump one i 










map jump8nc: 


0x63; 


// 


01100011 


= jump8nc #. . . 


+ 0 [7 : 0] =0x63; 










Up t; X. dULlo Up 1\J^ 

\ . 










J r 

op ]uinpo z i 










map jump8z: 


0x64; 


// 


01100100 


= jump8z #. . . 


+ 0 [7 : 0] =0x64; 










(jpti-L d-llU-b (jp ± O f 

\ . 










j ' 

r-\ v-\ — ITT TYT "V\ W V~l <~7 J 

op jumponz i 










map jump8nz : 


0x65; 


// 


01100101 


= jump8nz #. . . 


+ 0 [7 : 0] =0x65; 










/—\ y~\ £~\ y 3 n H o ati 1 C • 

(jpti-L cLll(J.b (jp ± O ^ 

\ . 










5 ' 

op junipoo i 










map jump8o: 


0x66; 


// 


01100110 


= jump8o #. . . 


+ 0 [7 : 0] =0x66; 










(jpti-L c±IlCJ.b (jp ± O ^ 

i . 










)' 

s~\ -v—, — ITT TV) VN W V~l / — >, J 

op ]uiupono i 










map jump 8 no: 


0x67; 


// 


01100111 


= jump8no #. . . 


+ 0 [7 : 0] =0x67; 










(jpti-L d-llU-b (jp ± O f 

\ . 










j ' 

/ — \ -y~\ — ITT TYT V~\ W V~l J 

op jurupon \ 










TY1 ;P T~") ~~ 1 1 "1 TY1T~") P T) " 
ILLdk-' J LllLLkJOll • 




// 


01 101000 


— iTimnPn ^ 

— JLllilfcJOll jf • • • 


+ 0 [7 : 0] =0x66; 










operands op_16; 











Version "C": 16-bit little-endian 



541 



1 . 

/' 

op jumponn -5 












map jumponn. 


UXDj, 


// 


U J. J. u± UU J. 




jumponn # . . . 


map op QTTOT . 


U X DA, 


// 


till U 1 Ul u 




A 7 1 j»"J 

TlOu Vallu 


map op qllot . 


U X Oo , 


// 


U 11 U 1 U 11 




nOTZ v3.HO. 


ITiap Op QTTOT . 


UXOt, 


// 


ni i ni i nn 

till till uu 




nOu V3.J.1CL 


ITiap Op QTTOT . 


U X OD , 


// 


ni i ni i ni 

U 11 Ul 1 Ul 




noiz v3.no. 


map Op QllOl . 


UXDli, 


// 


ni i ni 1 1 n 

Ull Ul 1 1U 




nou V3J.10 


rud-p op error . 


UXDr , 




ni i ni 1 1 1 

Ull Ul 111 




liOt vallu 


ILL dp Up t; J_ J_ U J_ • 


Ua/U, 


// 


ni i i nnnn 




iiUL vallu 


map op_error: 


0x71; 


// 


01110001 


= 


not valid 


+ 0 [7 : 0] =0x67; 












Upcl cLIlULb Up X O ^ 

\ . 












5 ' 

Up JUIILpXDL- 1 












map jumpl6c: 


0x72; 


// 


01110010 


= 


jumpl 6c #. . . 


+ 0 [7 : 0] =0x72; 












/~\ y 2 n H O /~\ y\ 1 C-\ • 

(jpcl cLllOLb (jp X O ^ 

\ . 












5 ' 

/ — \ -y~\ — ITT TY"1 V~\ H v~l / — i J 

op jump lone i 












map jumpl6nc: 


0x73; 


// 


01110011 


= 


jumpl 6nc #. . . 


+ 0 [7 : 0] =0x73; 












Up t: -L cLI lUb Up lu^ 

l. 












j ' 

Cjp J LilLip ± D Z 1 












map jumpl 6z : 


0x74; 


// 


01110100 


= 


jumpl 6z #. . . 


+0 [7:0]=0x74; 












/—\ Y~\ £2i T 2 H H O ATl 1 C « 

Upcl cLll(J.b Up ± O j 

\ . 












/' 

up j uiupx OIIZ 1 












map jumpl 6nz : 


0x75; 


// 


01110101 


= 


jumpl 6nz #. . . 


+0[7:0]=0x75; 












(jpcl cLllOLb Up ± O f 

\. 












op jumpl 6o { 












map jumpl6o: 


0x76; 


// 


01110110 




jumpl 6o #. . . 



542 



Version "C": 16-bit little-endian 



+ 0 [7 : 0] =0x76; 












(jpti-L c±llCJ.b (jp ± O ^ 

\ . 












5 ' 

Op JUILLpXOIlO 1 












map jumpl6no: 


0x77; 


// 


01110111 


= 


jumpl 6no #. . . 


+ 0 [7 : 0] =0x77; 












(jpti-L d-llU-b (jp ± O f 

\ . 












5 ' 

(jp J U.IUjJ± Oil 1 












map jumpl 6n : 


0x78; 


// 


01111000 


= 


jumpl 6n #. . . 


+ 0 [7:0]-0x76; 












Up t: -L cLI 1CJ.O Up lu^ 

i . 












op jumpxonn *j 












map jumpxonn. 


n ^ 7 q • 
ux/y. 


// 


U ±±±± UU J. 




jump J. 0 W • • • 


map op QTTOT . 


n v 7 b • 

UX / A, 


// 


UJ.J. x x C/x 1/ 




nOTZ V3.J.1CL 


map op error. 


n v n "n • 


// 


U XX X X l/X X 




J— a I ^ >™J 

nou vaxxQ 


map op error . 


n ^ 7 r 1 • 
UX / L, 


// 


n i i i i i nn 

UJ. x x x x C/l/ 




nOTZ V3.J.2.CL 


map op error . 


U X / JJ , 


/ / 


UJ. X XXX l/x 




nOL. VailU 


map op error . 


U X / Hi f 




l/X X X X X X 1/ 






map op_error: 


0x7F; 


// 


01111111 


= 


not valid 


+ 0 [7 : 0] =0x77; 












(jpti-L cLIl(J.b (jp ± O ^ 

\ . 












5 ' 

s~\ -y~\ -y~\ -\ -i o r~l >< J 

Cjp pUollO 1 




// 


± uuuu . . . 




pus no 


lLld.p pUoIlO _L . 


uxou, 


/ / 


X 1/ 1/ 1/ 1/ 1/ 1/ 1/ 




pusno ^> X 


ILldp pUoIlO J . 


uxor, 




7 nnnnnm 

x u u u u u U J. 




pusno ^> u 


ILld-P pUoIlO d. . 


n Y Q9 ■ 
UXOi , 




X l/l/l/l/l/X 1/ 




pusno 


nid-p puoiio U . 


UXO J, 




7 nnnnn 7 7 

X U U U U U ± X 




pusno ^ts 


rild.p pUSllC; Ijp . 


rivQ/i • 

UXol, 


/ / 


7 nnnn i nn 

X UUUU J. uu 




pusno 75 Dc 


ILLcip (jp L L (J J_ . 


n y p r • 

UXO J ( 


// 
// 


7 nnnm n 7 

Xl/l/l/l/Xl/X 




pUSnO o Oxr IJC'L VallU 


TYl T^i T^i n ch P TT1 H r ' 

ILLctl-' piioll O ILLd J_ . 




// 


7 nnnm 7 n 

XL/L/L/L/XXL/ 






ILLcip pUbllO -L _L . 


uxo / f 


// 
// 


7 nnnn 777 

Xl/l/l/l/XXX 




pusno on j-i 














operands { 












%1 = { +0 [2 : 0 


]=%!; 


}; 









Version "C": 16-bit little-endian 



543 



1 . 

s> 

\ . 

i ' 

up pupo 1 






7 nnm 

± UU V ± . . . 




popo 


ILLcip pupo _L . 


n Y QO. 
uxoo, 


/ / 


7 /I /I /1 7 /I /I /I 
X UUU J. u uu 




popo ^x 


ILLcip pupo J . 


uxor', 




7 /I /I /1 7 /I /1 7 

X UUU J. uu J. 




popo 1>U 


ILLcip pupo d. . 


flvQl • 
UXOfl, 




X 1/1/ l/X l/X 1/ 




popo ^ri 


Wl — 1 "V~\ "V~\ / — \ v~\ O V~\ ■ 

lUd-P popo IJ . 


UXOD, 




7 ODD 7/17 7 
X UUU X l/x x 




popo tSD 


ILLcip pupo JL)p . 






7 7 7 /I /I 
X UUU J. J. uu 




popo voir 


ILLcip (jp fc: L L U J_ . 




// 
// 


7 nnm i m 

J.UUUJ.J.UJ. 




popo o *JC UOL, vczXXCi 


TYl T~-i T~-i Oh T~"i P m Hr • 

ILLcip pup O ILLU. J_ . 


UAOJj^ 


// 


7 nnm 1 1 n 

XL/L/L/XXXL/ 




pOpO o 1. AU±\ 


mnn rir>riP ~f~ ~l • 
ILLdp pupO J L . 


uxor f 


// 


7 nnm 1 1 1 

X 1/ L/ 1/ X X X X 




popo VS J-i 


+ 0 [7 : 0] =0x88; 












operands -[ 












%1 = { +0 [2 : 

1 . 

S> 


o]=%i ; ; 










1 . 

5' 

Cjp pUbllXD 1 




// 


7 /I /I 7 O 

X UU J. u . . . 




mi aril f\ 

pusuj. O 


map pusnxo l . 


U X y U , 


// 


7 o/i 7 nnnn 
x l/C/x uuuu 




ni ieh 7 Q- T 

pusni o ^x 


map pusnio j . 


n v Q1 • 

uxyi, 


/ / 


7 7 nnm 

x uu ± UUU ± 




TIT 7 o h 7 9- T 


Illd-P pUfalll O d. . 


n Y Q9 • 


// 


7 /I /I 7 /I /I 7 /I 
X UU J. UU J. u 




t-itt e h 7 /\ 5-2 

pusnj. o 


lUd-P pUSIlXO JO. 




// 


7 /I/I 7 (1(1 7 7 
x 1/ L/X l/C/x X 




pus hj. o vd 


lLld.p pUoIll O Up . 




// 


7 /I /I 7/17 /I /I 
X UU J. l/X 1/1/ 




pUSill O voir 


ILLcip Up fc: -L J_ U L . 


n v q r • 


/ / 


7 /i/i 7 mm 

X l/l/X l/X l/X 




mjch 7 CD nnf rra 7 -f W 

pusnj. o o or^ iiu u vaxxu 


m :u t~\ t~\ n cVi 1 C~s m /H -y 
ILLcip pUoill U ILLU-L 


n v q ^ • 


// 


7 nm m i n 

Xl/l/Xl/XXl/ 




r-17 7 cfi7 /? SrMD R 

f/UOlil U o L 1LJ £\ 


ILLcip pUblll O -L _L . 


f|vQ7 • 
UXU / , 


// 
// 


7 /l/l 7 mil 

Xl/L/XL/XXX 






+ 0 [7 : 0] =0x90; 












operands -[ 












%1 = { +0 [2 : 

1 . 


o]=%i ; ; 


I; 








\ . 
i ' 

Up pup X 0 1 




// 


7 /l/l 7 7 

X l/l/X x . . . 




pop J. o 


ILLcip pupXO _L . 


flvQR • 
UXjo, 


// 


7 /l/l 7 7 /I /I /I 

X l/l/XX 1/1/1/ 




pop J. O 75 X 


iLlcip pupXO J . 




// 


7 /l/l 7 7 /l/l 7 

X l/l/XX l/l/X 




pop± O 75 U 


ILLdp pupx U CL . 




// 


7 ofli mm 

Xl/L/XXl/Xl/ 




pop J. V OA 


map popl6_b: 


0x9B; 


// 


10011011 




popl6 %B 


map popl6_bp: 


0x9C; 


// 


10011100 




pop!6 %BP 



544 



Version "C": 16-bit little-endian 



IlLcLJL? CJtJ t3J_J_(J-L . 


U x yu , 


// 


7 /I /I 7 7 7 /17 

Xl/L/XXXl/X 


— pop J. o 


5- CD n/-\-f- Trail W 

for nOL. Vcxxxu 


ILLcLp p(jpXO 1 1 LCJ. J_ . 




// 


7 ilrt 7 1 1 1 n 

XL/L/XXXXL/ 


— pop J. 0 




ILLcLp popXO -L _L . 




// 
// 


7 rtrt 7 7 7 7 7 

X 1/ L/X X X X X 


— pop J. 0 


&JTT 


+ 0 [7 : 0] =0x98; 












operands ^ 












%1 = { +0 [2 : 

1 . 
i > 


0]=%1; 


I; 








Cjp LOLU1DU 1 












map c8tol6u: 


OxAO; 


// 


10100000 






+0 [7 : 0] =0xA0; 












OptiJ-dllClb Op 

1 . 












J ' 

Op LOLUlub 1 












map c8tol 6s : 


OxAl; 


// 


10100001 






+0 [7 : 0] =0xAl; 












(jpt;l_ c±llCJ.b (jp U ^ 

i . 












j ' 

op ec[ua_i_ i 












map equal : 


0xA2; 


// 


10100010 






+0 [7 : 0] =0xA2; 












Cjpt;l_ d-llU-b (jp U f 

\ . 












)' 

<— , r~, r~\ o "I - < 
(jp I1U L 1 












map not : 


0xA3; 


// 


10100011 






+0[7:0]=0xA3; 












Opt; L d-ilU-b Cjp \J r 

\ . 












s ' 

Op cLilCL 1 












map and: 


0xA4 ; 


// 


10100100 






+ 0 [7 : 0] =0xA4; 












operanas op u , 

1 . 












i > 

c\y~\ n n H -< 

LJkJ llcLIlLJ. i 












map nand: 


0xA5; 


// 


10100101 






+0 [7 : 0] =0xA5; 













Version "C": 16-bit little-endian 



545 



operands op 0; 

}; 








Up U L 1 

map or: 

+0 [7 : 0] =0xA6; 


0xA6; 


// 


10100110 


operands op 0; 

}; 








Up I1U-L ^ 

map nor: 

+0 [7 : 0] =0xA7; 


0xA7; 


// 


10100111 


operands op 0; 

}; 








Up AUl 1 

map xor: 

+0 [7 : 0] =0xA8; 


0xA8; 


// 


10101000 


operands op 0; 

}; 








Up I1XU-L 1 

map nxor: 

+0 [7 : 0] =0xA9; 


0xA9; 


// 


10101001 


operands op 0; 

}; 








UjJ ctUU 1 

map add: 

+0 [7 : 0] =0xAA; 


OxAA; 


// 


10101010 


operands op 0; 

}; 








Up o LUJ 1 

map sub: 

+ 0 [7 : 0] =0xAB; 


OxAB; 


// 


10101011 


operands op 0; 

}; 








+0 [7 : 0] =0xAC; 


n v ap • 


/ / 


101011 00 


operands op_0; 









546 



Version "C": 16-bit little-endian 



1 . 

/' 

Op SUDDo \ 








map subb8 : 


OxAD; 


// 


10101101 


+0 [7 : 0] =0xAD; 








operanas op u , 

\ . 








)' 

Op duQCID 1 








map addcl6: 


OxAE; 


// 


10101110 


+0 [7 : 0] =0xAE; 








(jpt3 J! d.il(J.b (jp 

i . 








j ' 

Op bUJJJJXD 1 








map subbl6: 


OxAF; 


// 


10101111 


+0 [7 : 0] =0xAF; 








Opt; L d-ilClb Op 

1 . 








J l 

op _i_ sni o i 








map lshl8: 


OxBO; 


// 


10110000 


+ 0 [7 : 0] =0xB0; 








OptiJ-d.ilQb Op \J r 

\ . 








)' 

Op _L bil-L O 1 








map lshr8: 


OxBl; 


// 


10110001 


+ 0 [7 : 0] =0xBl; 








OpeldllUb Op 

1 . 








)' 

op asn_L o i 








map ashl8: 


0xB2; 


// 


10110010 


+ 0 [7 : 0] =0xB2; 








Opte!-L d.ilUb Op 

1 . 








)' 

op dsnro i 








map ashr8: 


0xB3; 


// 


10110011 










operands op 0; 

}; 









Version "C": 16-bit little-endian 



547 



op lOUClo 1 








map rotcl8: 


0xB4 ; 


// 


10110100 


+ 0 [7 : 0] =0xB4; 








operands op 0; 

1 . 








)' 

op roici o i 








map rotcr8: 


0xB5; 


// 


10110101 


+ 0 [7 : 0] =0xB5; 








operanas op u , 

\ . 








i > 

Op Jl O L _L O 1 








map rotl8: 


0xB6; 


// 


10110110 


+ 0 [7 : 0] =0xB6; 








operanas op u , 








i > 

Op lOlL O 1 








map rotr8: 


0xB7; 


// 


10110111 


+ 0 [7 : 0] =0xB7; 








operands op 0; 

1 . 








i i 

Op -L Sil_L X 0 1 








map lshll6: 


0xB8; 


// 


10111000 


+ 0 [7 : 0] =0xB8; 








operanas op u, 

1 . 








)' 

op isnriD i 








map lshrl6: 


0xB9; 


// 


10111001 


+ 0 [7 : 0] =0xB9; 








operands op 0; 








i > 

op dsni id i 








map ashll6: 


OxBA; 


// 


10111010 


+0 [7 : 0] =0xBA; 








}; 








op ashrl6 { 









548 



Version "C": 16-bit little-endian 



map ashrl6: 


OxBB; 


// 10111011 


+ 0 [7 : 0] =0xBB; 






operands op 0; 

\ . 






op rotciio i 






map rot ell 6 : 


OxBC; 


// 10111100 


+ 0 [7 : 0] =0xBC; 






operands op 0; 

1 . 






i i 

op roLcrxo i 






map rotcrl6: 


OxBD; 


// 10111101 


+ 0 [7 : 0] =0xBD; 






operands op 0; 

1 . 






i i 

op r or no i 






map rotll6: 


OxBE; 


// 10111110 


+ 0 [7 : 0] =0xBE; 






operands op 0; 

1 . 






)' 

op r or riu i 






map rotrl6: 


OxBF; 


// 10111111 


+ 0 [7 : 0] =0xBF; 






A-no n H o /~\ y\ C] • 






s ' 

op in 






map in: 


OxCO; 


// 11000000 


+ 0 [7 : 0] =0xC0; 






Opt; L d-ilClfa Op O, 

1 . 






J 1 

op our i 






map out : 


OxCl; 


// 11000001 


+ 0 [7 : 0] =0xCl; 






/~\ y~\ £~\ y 2 n H O /~\ y~\ Q • 

CJ|Jt;J_ d-llU-b (JjJ O f 






s ' 

op ifack_jump { 






map ifack_jump 


: 0xC2; 


// 11000010 



Version "C": 16-bit little-endian 



549 



map op_error: 0xC3; // 11000011 
+ 0 [7 : 0] =0xC2; 
operands { 

#1,#2 = { +1=#1[7:0]; +2=#1[7:0]; +3=#2[17:8]; }; 

}; 

}; 

op clearc { 

map clearc: 0xC4; // 11000100 
+ 0 [7 : 0] =0xC4; 
operands op_0; 

}; 

op setc { 

map setc: 0xC5; // 11000101 

+ 0 [7 : 0] =0xC5; 
operands op_0; 

}; 

op cmp { 

map cmp: 0xC6; // 11000110 

+ 0 [7 : 0] =0xC6; 
operands op_0; 

}; 

op test { 

map test: 0xC7; // 11000111 

+ 0 [7 : 0] =0xC7; 
operands op_0; 

}; 

op imrl { 

// IMR load 



map 


imrl : 


0xC8; 


// 


11001000 


map 


op_ 


.error : 


0xC9; 


// 


11001001 


map 


op_ 


.error : 


OxCA; 


// 


11001010 


map 


op_ 


.error : 


OxCB; 


// 


11001011 


map 


op_ 


.error : 


OxCC; 


// 


11001100 


map 


op_ 


.error : 


OxCD; 


// 


11001101 


map 


op_ 


.error : 


OxCE; 


// 


11001110 


map 


op_ 


.error : 


OxCF; 


// 


11001111 


+ 0 [7 


:0] 


=0xC8; 









550 



Version "C": 16-bit little-endian 



Opt; L d-ilClb Op O, 

\ . 














J ' 

op inc 














map inc 1 . 


U XJJ u , 


// 


jL x L/x UUUU 




inc 


Sr T 

■si 


map inc j . 


U XJJ 1 , 


// 


7 7/17 /I /I /I 7 
x X L/x UUU X 




inc 


S- T 


map mc a . 


U XJJ z , 


// 


7 7/17 /I /I 7 /I 
x x L/x L/L/x L/ 




inc 


a- a 


map mc d . 


U XL) o r 


// 


7 7/17 /I /I 7 7 
X X L/x L/L/x X 




inc 


-5jO 


riiap mc op . 


U KL) *± , 


// 


7 7/17/17 /1/1 
X X L/x L/x C/C/ 




inc 




lud-p inc sp . 


U XJJ D , 


// 


7 7/17/17/17 
X X L/x L/x L/x 




inc 


9? CD 


m -| r~i m H r • 
ILLcl|J _L 1 1 luLlX. • 




// 


77/17/177/1 
XXL/XL/XXL/ 


// 


_L i i 




m ^ t~\ n r~\ r~< t 1 • 
1LlcL,U _L 1 1 J L • 




// 


77/17/1777 
XXL/XL/XXX 


/ / 


XiiC 


o £ ±J 


+ 0 [7 : 0] =0xD0; 














operanas ^ 














%1 = { +0 [2 : 

\ . 


0]=%1; 


}; 










\ . 

5 ' 

op aec 














map de c i c 


u xjj o ; 


/ / 


7 7 /17 7 nnn 
11U11UUU 


// 


dec 


g, -r 
Si 


map dec j : 


u xjj y ; 


// 


7 7/17 7/1/17 
xxC/xxC/C/x 


// 


dec 




map aec a. 


U XUA, 


// 


77/177/17/1 
x x L/x x L/x 1/ 


// 


dec 


-5/1 


Wl — 1 V\ /""N f — \ / — 1 V"\ • 

map ae c d . 


U XJJJd , 


/ / 


77/177/177 
X X L/X X l/x X 


/ / 


dec 


SD 


map aec Dp. 


U XJJL. , 


// 


7 7 /17 7 7 /1/1 
x x L/x x x 1/1/ 


// 


dec 


Stic 


map aec sp . 


U XJJJJ , 


/ / 


77/1777/17 
X X L/X X X L/x 




dec 


& CD 


IIIgLU CLt;0 ITLCJL J_ . 


U XJJH] , 




77/17777/1 

XXL/XXXXL/ 






5-A/fDP 


map aec n . 


U XJJr , 




77/177777 

X X L/X X X X X 




dec 




map op error. 


U XJj u , 




777 nnnni 

xxx UUUU J. 








map op error. 


U XJj 1 i 




7 7 7 /I /I /I 7 /I 
xxx UUU X 1/ 








map op error. 


U XJjZ , 




7 7 7 /I /I /I 7 7 
xxx L/ L/L/x X 








map Op tei-L-LO-L . 


U XJj 4 , 




7 7 7 /I /I 7 /I /I 

XXX 1/ L/X 1/1/ 








map op error. 


U XJJij , 


/ / 


7 7 7 /I /I 7/17 
xxx L/L/x l/x 








map op error. 


U Xti o , 




7 7 7 /I /I 7 7/1 
xxx L/L/x x 1/ 








map op error. 


U Xti / , 


/ / 


7 7 7 /I /I 7 7 7 
xxx L/L/x X X 








md.p Op t3J_J_OJ_ . 


U Xti O f 


/ / 


7 7 7 /17 /1/1/1 
xxx l/x UUU 








ILLcLk-' J_ J_ \J X. • 




/ / 


1 1 101001 








map op_error: 


OxEA; 


// 


11101010 








map op_error: 


OxEB; 


// 


11101011 









Version "C": 16-bit little-endian 



551 



map 


op error . 






XXX l/X X 1/1/ 


map 


op error . 


U XH/JJ , 


// 


XXX l/X X l/X 


map 


op error . 


U X£j1j , 




77707770 

XXX l/X XXI/ 


map 


op error . 


U Xiji , 




77707777 

XXX l/X XXX 


map 


op error . 


U AC U , 




7777 nnni 

X X X X 1/1/ l/X 


map 


op error . 


U AC X , 




7777 OO 7 O 
X X X X 1/ l/X 1/ 


map 


op error . 


U AC Z , 




7777 OO 7 7 
X X X X 1/ l/X X 


map 


op error . 


U AC '-i f 


/ / 


777707 OO 

X X X X l/X 1/1/ 


map 


op error . 


U AC O , 


/ / 


77770707 

X X X X l/X l/X 


map 


Op te! IIUI . 


UXI 0 i 


/ / 
// 


7777/177/1 

XXXXl/XXl/ 


map 


Op teJ-LJ-O-L . 


U AI / r 




7777/1777 

X X X X l/X X X 


map 


Op te! J_ J_ O Jl . 


U xr o , 




7 7 7 7 7 /I /I /I 

XXXXXl/l/l/ 


map 


Op te! J.IOI . 


U Xr r 




7 7 7 7 7 /I /1 7 

XXXXXl/l/X 


map 


op error . 


U Xr A, 




77777070 

X X X X X l/X 1/ 


map 


op error . 


U Xr Jd , 


/ / 


77777077 

X X X X X l/X X 


map 


Op teJ-LJ-O-L . 


U xr , 




7 7 7 7 7 7 /1/1 

XXXXXXl/l/ 


ILLdp 


Op fc! L L O -L . 




// 
// 


777777/17 

XXXXXX l/X 


map 


op_error : 


f\ v"FT''F • 
UXI 


// 
// 


7777777/1 

XXXXXXXl/ 


+ 0 [7 


: 0] =0xD8; 








operands { 








2- 1 

}■ 


= { +0[2: 


0]=%1; 


}; 




}; 

op stop { 








map 


stop : 


OxFF; 


// 


12211112 


+ 0 [7 


: 0 ] =0xFF; 








operands op 0; 

}; 









Table 10.37. Macrocode syntax. 



Macrocode syntax 


Binary opcode 


Description 


nop 


00000000 


Not operate: does not to any- 
thing. 



552 



Version "C": 16-bit little-endian 



Macrocode syntax 


Binary opcode 


Description 


mv %src , %dst 


0 0 sssddd 


Copy the src register content in- 
side the dst register. Allowed 
registers are: /, J, A, B, BP, 
SP, MDR, FL. The opcode 
00000000 2 remains for the nop 
instruction because it would 
represent the copy of register A 
into the same register A . 


load8 (%l|%J) 
load 8 address 
loadl6 (%l|%J) 
load 16 address 


010 0010* 
01000110 
010 0100* 
01001010 


Load inside the MDR register 
an 8 -bit or 16-bit value from the 
memory. The argument might be 
an index register (/ or J) and 
in that case the bit i is used to 
distinguish the register inside the 
opcode; otherwise, the argument 
can be directlv the memorv ad- 
dress and the last two bits of the 
opcode are equal to 10 2 . 


store8 (%I | %J) 
st ore 8 address 
storel6 (%I | %J) 
load 16 address 


010 01 10/ 
01001110 
0101000/ 
01010010 


Store in memory (eight or six- 
teen bits), at the address speci- 
fied by the argument, the value 
contained inside the MDR reg- 
ister. If the argument is an index 
register (/ or /), then the bit i 
is used to distinguish the regis- 
ter inside the opcode; otherwise, 
the argument can be directly the 

mpmrvrv nHHvpQQ nnH ttip lust twn 

llldllUlj dUUltoo dllll lilt Idol iwu 

bits of the opcode are equal to 
10 2 . 


cp8 (%l|%J) 
cp!6 (%I | % J) 


0101010s 
0101011s 


Copy from RAM memory to 
RAM memory eight or sixteen 
bits, starting from the position 
represented by the content of the 
index register soecified to the 

lllvJVi V A -K- LX Wl LX 1— ' WlllvV.lt VV V11V 

position represented by the con- 
tent of the other index register. 



Version "C": 16-bit little-endian 



553 



Macrocode syntax 


Binary opcode 


Description 


return 
call #ref 
call (%l|%J) 


01011000 
01011001 
0101101/ 


Return from ad call to a routine. 
The bit i represents an index reg- 
ister (/ o /). The call instruc- 
tion push the register PC onto 
tne stacK, wnne tne return in- 
struction restore the register PC 
from the stack. 


int n_interrupt 

iret 


01011100 
01011101 


Interrupt call and interrupt re- 
turn; the size of the argument 
njnterrupt is 8 -bit, but can be 
only a value from zero to six- 
teen. When the int instruction 
is encountered, the registers FL 
and PC are saved inside the 
stack and then the IRQ enable 
flag is zeroed; when an iret in- 
struction is encountered, tne reg- 
isters PC and FL are restored 
from the stack. 


cleari 
set i 


01011110 
01011111 


Reset or set the hardware inter- 
rupts nags, contained mside the 
FL register. 


ivtl #ref 


01100000 


Load the IVT: interrupt vector 
table The argument is the inter- 
rupt vector table start address in 
memory. 


jump #ref 


01100001 


Jump to the address specified. 



554 



Version "C": 16-bit little-endian 



Macrocode syntax 


Binary opcode 


Description 


jump 8c #ref 


01100010 




jump8nc $ref 
jump8z %ref 
jump8nz $ref 
jump 80 %ref 
jump8no #ref 
jump8n #ref 


01100011 
01100100 
01100101 
01100110 
01100111 
01101000 


Jump to the instruction located 
at the specified address if: the 8- 
bit carry flag is active, the 8-bit 
carry flag is not active, the 8-bit 
zero flag is active, the 8 -bit zero 
flag is not active, the 8-bit over- 
flow flag is active, the 8 -bit over- 
flow flag is not active, the 8-bit 
sign flag is active, the 8 -bit sign 
flag is not active. 


jump8nn %ref 


01101001 




jump 16c #re/ 


01110010 




jumpl6nc %ref 
jumpl6z #ref 
jumpl6nz #ref 
jumpl6o #ref 
jumpl6no %ref 
jumpl6n $ref 


01110011 
01110100 
01110101 
01110110 
01110111 
01111000 


Jump to the instruction located at 
the specified address if: the 16- 
bit carry flag is active, the 16-bit 
carry flag is not active, the 16- 
bit zero flag is active, the 16-bit 
zero flag is not active, the 16-bit 
overflow flag is active, the 16- 
bit overflow flag is not active, the 
16-bit sign flag is active, the 16- 
bit sign flag is not active. 


jumpl6nn #ref 


01111001 





Version "C": 16-bit little-endian 



555 



Macrocode syntax 


Binary opcode 


Description 






Push on top of the stack the 8- 






bit rontpnt of flip snprifipH tpp- 


push 8 % register 


lOOOOrrr 


ister, otherwise restore the spec- 
ified register removing the last 


pop 8 ^register 


100 01/7T 


8 -bit value from the top of the 

SlaCK. r ICaSC nOLlCC trial LilC pUSil 

and pop or the if register is not 
valid. 






Push on top of the stack the 16- 






bit rontpnt of thp snprifipd i~pp- 


push 16 % register 


lOOlOrrr 


ister, otherwise restore the spec- 
ified register removing the last 


pop 16 % register 


lOOllrrr 


16-bit value from the top of the 
siacK. r lease notice tnai ine pusn 
and pop of the SP register is not 

villi H 


c8tol 6u 


10100000 


Change the A value to a 8-bit un- 


c8tol 6s 


10100001 


signed or signed. 


equal 


10100010 




not 


10100011 




and 


10100100 




nand 


10100101 


Logical operation starting from 
the values contained inside the 


or 


10100110 


registers A and B, placing the 
result back to the A register. 


nor 


10100111 




xor 


101001000 




nxor 


10101001 





556 



Version "C": 16-bit little-endian 



Macrocode syntax 


Binary opcode 


Description 






Addition or subtraction: A+B or 


add 


10101010 


A — ft The nrevions rarrv or bor- 
row is not taken into consider- 
ation, but the result will update 


cjn V") 


1 01 01 01 1 


ine new carry or doitow. i ne re- 
sult is saved inside the A regis- 
ter. 


addc8 


10101100 


Addition or subtraction with 


subb8 


10101101 


rvrevions rarrv or borrow* 

A+B+carry or A-B -borrow . 
The result is saved inside the 


addcl 6 


10101110 


A register. The number eight 
or sixteen is useci to seieci ine 


subbl 6 


10101111 


input carry or borrow. 


lshl8 


10110000 




lshr8 


10110001 




ashl8 


10110010 




ashr 8 


10110011 


Bit shift and rotation with 8 -bit 
size, over the original A register 


rotcl8 


10110100 


value, placing the result on the 
same A register. 


rot cr 8 


10110101 




rotl8 


10110110 




rot r 8 


10110111 





Version "C": 16-bit little-endian 



557 



Macrocode syntax 


Binary opcode 


Description 


lshll6 


10111000 




lshr 1 6 


10111001 




ashll6 


10111010 




ashr 1 6 


10111011 


Bit shift and rotation with 16-bit 
size, over the original A register 


rotcll 6 


10111100 


value, placing the result on the 
same A register. 


rot cr 1 6 


10111101 




rotll6 


10111110 




rot r 1 6 


10111111 








RpaH or writp n v^iliip £it thp 






I/O address specified. The I/O 






address is a 8 -bit number For 


in io 


11000000 


is_ack it is checked the confir- 
mation facknowlpdpp^ from the 


out io 


11000001 


device and, if there is one, the 
condition is verified and a jump 


ifack_jump io , #ref 


11000010 


is done to the address specified 
as the last argument. Currently, 
oniy tne screen aevice can oe 
used with the ifack_jump in- 
strnrti on 


clearc 


11000100 


Clear or set the carry flags inside 


setc 


11000101 


the FL register. 



558 



Version "C": 16-bit little-endian 



Macrocode syntax 


Binary opcode 


Description 


cmp 
test 


11000110 
11000111 


Compare registers A and B, 
simulating a subtraction or the 
AND, just to update the flags in- 
side the FL register. 


imrl mask 


11001000 


Load the hardware interrupt 
mask: the active bits are related 
to interrupts to be enabled. The 
argument is a 8-bit number, but 
onlv the least significant four 
bits are used (there are only four 
hardware interrupts). 


inc ^register 
dec ^register 


HOlOrrr 
11011m* 


One unit increment or decre- 
ment, to the specified register, 
which is written at the last tree 
bits inside the opcode. 


stop 


11111111 


CPU halt, locking the clock sig- 
nal. 



10.10 Microcode 

« 

Listing 10.38. Fields of the microcode word, for TKGate. 



field 


Ctrl [1 : 0] 


= {nop=0, stop=l / load=2}; 




field 


pc [10:2] 


= {br=l, bw=2, aux=4, low=8, high=16, 








pl=32, p2=64, ml=128, m2=256}; 




field 


sel [15: 11] 


= {if_carry_8=l , if_not_carry_8=3 / 








if_zero_8=5, if_not_zero_8=7 , 








i f _negat i ve_8 = 9 , i f _not_negat i ve_8 


= 11, 






if_overf low_8=13 , if_not_overf low_ 


8 = 15, 






if_carry_16=l, if_not_carry_16=3, 








if_zero_16=5, if_not_zero_l 6=7 , 








i f _negat i ve_l 6=9, i f _not_negat i ve_ 


16=11, 






if_overf low_16=13, if_not_overf low 


_16=15}; 


field 


mdr [24 : 16] 


= {br=l, bw=2, aux=4, low=8, high=16, 








pl=32, p2=64, ml=128, m2=256}; 




field 


i [33:25] 


= {br=l, bw=2, aux=4, low=8, high=16, 





Version "C": 16-bit little-endian 



559 









-r-.-l—OO r\0 — £A ml— 19Q mQ-TCcl. 

pi-jz, pz-oi, ini-izo, niz — zoo 


rieia 


-i r A 9 • "5 ZL 1 




ijoj_ — ± r jow— z , dux-4, low-o, nign— id, 

pi — jZ, pZ-O'l, Ilil-IZo, luZ — ZOOj, 


field 


ram [47 : 43] 


= 


{br=l, bw=2, aux=4, p=0, i=8, j=l 6 , s=24}; 


rieia 


lvt LOU . 4 O J 




f"K -v~ — 1 "Ktt — O -ir->-t--i — H -l r-» 4- — /I \ • 

|Dl-l, DW-Z, lnta-u, 1I1LD-4|; 


-F i a 1 H 
J_ It! 1(_1 


-i -r T R Q • R 1 1 




idi — i , sjvj — z ( dux — '-if low — iiiy n — io f 

-r-.i—oo r->9 — £ Zl ml— 1 9fi m9 — 9R£\- 
pi — JZ f pZ — f IIll — 1ZO/ IllZ — ZOOff 


field 


bus [77 : 60] 


= 


{bw=0xl0000, aux=0x20000}; 


J_ It! 1(_1 


1 1 g L o U . / o J 




lui — i A ijw-z, uone-ij, 


field 


sp[89:81] 


= 


{br=l, bw=2, aux=4, low=8, high=16, 

„-! _oo r-,9 — aa ml— 19Q m9— 9R£\- 
pi — JZ | pZ — D4| I[L1 — IZOf IllZ — ZOOff 


field 


bp [98 : 90] 


= 


{br=l, bw=2, aux=4, low=8, high=16, 

y-.-i—OO r~i9 — £ Zl ml— 1 ?fi m9 — 9Rfil- 
pi — o z, f pz — 0 4, nil — izo, iiiz — ZJO r, 


field 


b [107 : 99] 


= 


{br=l, bw=2, aux=4, low=8, high=16, 

y-.i—oo r~i9 — £ Zl ml— 1 9fi m9 — 9R(;1- 

pi — o z. f pz — 0 4, nil — izo, iiiz — zooff 


field 


fl [116: 108] 




{br=l, bw=2, aux=4, low=8, high=16, 
pl=32, p2=64, ml=128, m2=256}; 


field 


alu [127 : 117] 


= 


{bw=l, aux=2, sign=4, rank8=0, rankl6=8, 
a=0, and=16, or=32, xor=48, 
nxor=64, nor=80, nand=96, not=112, 
add=256, sub=228, addc=320, subb=352, 
lshl=512, lshr=528, ashl=484, ashr=560, 
rotcl=576, rotcr=592, 
rotl=768, rotr=784, 

clearc=1024, clearz=1040, clearn=1056, 
clearo=1072, cleari=1088, 
setc=1152, setz=1168, setn=1184, 

cof n-1 900 oaf i -1 9Kl ■ 

beLO-izuu, beLi-izi Oj , 


field 


a[136:128] 


= 


{br=l, bw=2, aux=4, low=8, high=16, 

-r-.-l—OO r\0 — £A ml -1 9R m9 — 9Rfil. 

pi — O z r pz- uii-izo, mz-zjuj, 


1 1 te: 1 (J. 


lUd [14 J . 1 J / J 




i V"~» T~ I V^TaT 9 3nv Zl ~\ /^TaT — Q T~i n /~tT~i — 1 £-\ 

1 D 1 — 1 ^ UW — Z ^ cL UX — "-if 1CJW — O ^ 11 1 y 11 — lO^ 

pl=32, p2=64, ml=128, m2=256}; 


field 


ioc [149 : 146] 




{br=l, bw=2, req=4, isack=8}; 



560 



Version "C": 16-bit little-endian 



Listing 10.39. Microcode. 



beg 


in microcode @ 0 










// 












// 


fetch: 










// 


IR < — RAM[pc++] ; load; 










// 














ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl ctrl=load; 




// 












nop 


// fetch: 












ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl ctrl=load; 




op_ 


error : 
// INT 0 
// push FL 












sp=m2 ; 




// 


SP < — (SP - 


2) 




ram=br ram=s fl=bw fl=low sp=pl; 




// 


RAM[sp++] <- 


FL[7:0]; 




ram=br ram=s fl=bw fl=high sp=ml; 




// 


RAM[sp — ] <- 


FL[15:8]; 




// reset Interrupt enable flag 












fl=br fl=aux alu=cleari; 












// push PC 












sp=m2 ; 




// 


SP < — (SP - 


2) 




ram=br ram=s pc=bw pc=low sp=pl; 




// 


RAM[sp++] <- 


PC [7:0]; 




ram=br ram=s pc=bw pc=high sp=ml; 




// 


RAM[sp — ] <- 


PC [15: 8]; 




// push I 












sp=m2 ; 




// 


SP < — (SP - 


2) 




ram=br ram=s i=bw i=low sp=pl; 




// 


RAM[sp++] <- 


I [7:0]; 




ram=br ram=s i=bw i=high sp=ml; 




// 


RAM[sp — ] <- 


I [15: 8]; 




// 












i=br ivt=bw ivt=intb bus=bw bus=aux 


bus=0 ; 


// I <~ 


IVT <- 0; 




pc=br pc=low ram=bw ram=i i=pl; 




// PC [7:0] <— 


RAM[±++] 




pc=br pc=high ram=bw ram=i i=ml; 




// PC [15: 7] <— 


RAM[i — ] 




// POP 1 












i=br i=low ram=bw ram=s sp=pl; 




// 


I [7:0] < — RAM[sp++]; 




i=br i=high ram=bw ram=s sp=pl; 




// 


I [15:0] < — RAM[sp++]; 




// fetch 












ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl ctrl=load; 




mv_ 


i_j : 












j=br i=bw 




// 


J <- I, fetch; 




ir=aux ir=br ram=aux ram=bw ram= 


=P 


pc=pl ctrl=load; 




mv_ 


i_a : 












a=br i=bw 




// A <- I, fetch; 




ir=aux ir=br ram=aux ram=bw ram= 


=P 


pc=pl ctrl=load; 





Version "C": 16-bit little-endian 



561 



mv_ 


i_b: 






















b=br i=bw 


















// B <- I, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


i_bp : 






















bp=br i=bw 


















// BP <- I, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


i_sp : 






















sp=br i=bw 


















// SP <- I, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


i_mdr : 






















mdr=br i=bw 


















// MDR <- I, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


i_fl : 






















fl=br i=bw 


















// FL <- I, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 
























i=br j=bw 


















// J <- J, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


j_a: 






















a=br j=bw 


















// A <- J, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


j_b: 






















b=br j=bw 


















// B <- J, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


j_bp: 






















bp=br j=bw 


















// BP <- J, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


j_sp: 






















sp=br j=bw 


















// SP <- J, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


j_mdr : 






















mdr=br j=bw 


















// MDR <- J, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


j_fl: 






















fl=br j=bw 


















// FL <- J, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


a_i : 






















i=br a=bw 


















// J <- A, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


a_j : 






















j=br a=bw 


















// J <- A, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 



562 



Version "C": 16-bit little-endian 



mv_ 


_a_b : 






















b=br a=bw 


















// B <- A, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_a_bp : 






















bp=br a=bw 


















// BP <- A, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_a_sp : 






















sp=br a=bw 


















// SP <- A, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_a_mdr : 






















mdr=br a=bw 


















// MDR <- A, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_a_f 1 : 






















fl=br a=bw 


















// FL <- A, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_b_i: 






















i=br b=bw 


















// J <- B, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_b_j: 






















j=br b=bw 


















// J <- B, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_b_a : 






















a=br b=bw 


















// A <- B, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_b_bp : 






















bp=br b=bw 


















// BP <- B, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_b_sp : 






















sp=br b=bw 


















// SP <- B, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_b_mdr : 






















mdr=br b=bw 


















// MDR <- B, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_b_f 1 : 






















fl=br b=bw 


















// FL <- B, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_bp_i : 






















i=br bp=bw 


















// J <- BP, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 


mv_ 


_bp_j : 






















j=br bp=bw 


















// J <- BP, fetch; 




ir=aux ir 


=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 



Version "C": 16-bit little-endian 



563 



mv_ 


_bp_a : 






















a=br bp=bw 
















// A <- BP, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_bp_b : 






















b=br bp=bw 
















// B <- BP, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_bp_sp : 






















sp=br bp=bw 
















// SP <- BP, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_bp_mdr : 






















mdr=br bp=bw 
















// MDR <- BP 


, fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_bp_f 1 : 






















fl=br bp=bw 
















// FL <- BP, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_sp_i : 






















i=br sp=bw 
















// J <- SP, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_sp_j : 






















j=br sp=bw 
















// J <- SP, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_sp_a : 






















a=br sp=bw 
















// A <- SP, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_sp_bp : 






















bp=br sp=bw 
















// BP <- SP, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_sp_b : 






















b=br sp=bw 
















// B <- SP, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_sp_mdr : 






















mdr=br sp=bw 
















// MDR <- SP, fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_sp_f 1 : 






















fl=br sp=bw 
















// FL <- SP, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_mdr_i : 






















i=br mdr=bw 
















// J <- MDR, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 




mv_ 


_mdr_ j : 






















j=br mdr=bw 
















// J <- MDR, 


fetch; 




ir=aux ir=br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc 


=pl ctrl=load; 





564 



Version "C": 16-bit little-endian 



mv_ 


_mdr_bp : 
















bp=br mdr=bw 












// BP <- MDR, fetch; 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_mdr_sp : 
















sp=br mdr=bw 












// SP <- MDR, fetch; 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_mdr_b : 
















b=br mdr=bw 












// B <- MDR, fetch; 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_mdr_a : 
















a=br mdr=bw 












// A <- MDR, fetch; 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_mdr_f 1 : 
















fl=br mdr=bw 












// FL <- MDR, fetch; 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_f l_i : 
















i=br fl=bw 












// J <- FL, fetch; 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_f l_j : 
















j=br fl=bw 












// J <- FL, fetch; 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_fl_a: 
















a=br fl=bw 












// A <- FL, fetch; 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_fl_bp: 
















bp=br fl=bw 












// BP <- FL, fetch 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_f l_sp : 
















sp=br fl=bw 












// SP <- FL, fetch 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_f l_mdr : 
















mdr=br fl=bw 












// MDR <- FL, fetch 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


mv_ 


_fl_b: 
















fl=br b=bw 












// B <- FL, fetch 




ir=aux ir=br 


ram=aux 


ram=bw 


ram= 


=P 


pc= 


pi ctrl=load; 


load8_i : 
















mdr=br ram=bw 


ram=i ; 










// MDR <- RAM[i ] ; 




ir=aux ir=br ram=aux ram=bw ram=p 


pc=pl 


ctrl=load; // fetch 


load8_j : 
















mdr=br ram=bw 


ram= j ; 










// MDR <- RAM[j ] ; 




ir=aux ir=br ram=aux ram=bw ram=p 


pc=pl 


ctrl=load; // fetch 



Version "C": 16-bit little-endian 



565 



load8 : 










i=br i = 


=low ram=bw ram=p pc=pl; 






// I [7:0] <- RAM[pc++] ; 


i=br i = 


=high ram=bw ram=p pc=pl; 






// I [15: 8] <- RAM[pc++]; 


mdr=br 


ram=bw ram=i; 






// MDR <- RAM[i ] ; 


ir=aux 


ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


loadl 6_i : 










mdr=br 


mdr=low ram=bw ram=i i=pl; 






// MDR[7:0] <- RAM[±++] ; 


mdr=br 


mdr=high ram=bw ram=i i=ml; 






// MDR[15:8] <- RAM [ i — ]; 


ir=aux 


ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


loadl 6_ j : 










mdr=br 


mdr=low ram=bw ram=j j=pl; 






// MDR[7:0] <- RAM[j++] ; 


mdr=br 


mdr=high ram=bw ram=j j=ml; 






// MDR[15:8] <- RAM[j — ]; 


ir=aux 


ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


loadl 6 : 










i=br i = 


=low ram=bw ram=p pc=pl; 






// I [7:0] <- RAM[pc++ ] ; 


i=br i = 


=high ram=bw ram=p pc=pl; 






// I [15: 8] <- RAM[pc++] ; 


mdr=br 


mdr=low ram=bw ram=i i=pl; 






// MDR[7:0] <- RAM[i++] ; 


mdr=br 


mdr=high ram=bw ram=i i=ml; 






// MDR[15:8] <- RAM[i — ]; 


ir=aux 


ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


store8_i : 










ram=br 


ram=i mdr=bw; 






// RAM[i ] <- MDR [7:0]; 


ir=aux 


ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


store8_j : 










ram=br 


ram=j mdr=bw; 






// RAM[j] <- MDR [7:0]; 


ir=aux 


ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


store8 : 










i=br i = 


=low ram=bw ram=p pc=pl; 






// I [7:0] <- RAM[pc++] ; 


i=br i = 


=high ram=bw ram=p pc=pl; 






// I [15: 8] <- RAM[pc++]; 


ram=br 


ram=i mdr=bw; 






// RAM[i ] <- MDR [7:0]; 


ir=aux 


ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


storel 6_i : 










ram=br 


ram=i mdr=bw mdr=low i=pl; 






// RAM[±++] <- MDR[7:0]; 


ram=br 


ram=i mdr=bw mdr=high i=ml; 






// RAM[i — ] <- MDR [15: 8] ; 


ir=aux 


ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


storel 6_j : 










ram=br 


ram=j mdr=bw mdr=low j=pl; 






// RAM[j++] <- MDR [7:0]; 


ram=br 


ram=j mdr=bw mdr=high j=ml; 






// RAM[j — ] <- MDR[15:8] ; 


ir=aux 


ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


storel 6 : 










i=br i = 


=low ram=bw ram=p pc=pl; 






// I [7:0] <- RAM[pc++] ; 


i=br i = 


=high ram=bw ram=p pc=pl; 






// I [15: 8] <- RAM[pc++] ; 


ram=br 


ram=i mdr=bw mdr=low i=pl; 






// RAM[i++] <- MDR [7:0]; 



566 



Version "C": 16-bit little-endian 



ram=br ram=i mdr=bw mdr=high i=ml; // RAM[i — J <— MDR[15 : 8] ; 

ir=aux ir=br ram=aux ram=bw ram=p pc=pl ctrl=load; // fetch 
cp8_i j : 

mdr=br ram=bw ram=i i=pl; // MDR[7:0] <- RAM[i++] ; 

ram=br ram=j mdr=bw j=pl; // RAM[j++] <- MDR[7:0]; 

ir=aux ir=br ram=aux ram=bw ram=p pc=pl ctrl=load; // fetch 
cp8_j i : 

mdr=br ram=bw ram=j j=pl; // MDR[7:0] <- RAM[ ; 

ram=br ram=i mdr=bw i=pl; // RAM[i++] <- MDR[7:0]; 

ir=aux ir=br ram=aux ram=bw ram=p pc=pl ctrl=load; // fetch 
cpl 6_i j : 

mdr=br mdr=low ram=bw ram=i i=pl; // MDR[7 : 0] <— RAM ; 

mdr=br mdr=high ram=bw ram=i i=pl; // MDR[15 : 8] <— RAM ; 

ram=br ram=j mdr=bw mdr=low j=pl; // RAM [ <— MDR[7 : 0] ; 

ram=br ram=j mdr=bw mdr=high j=pl; // RAM [ <— MDR [15 : 0] ; 

ir=aux ir=br ram=aux ram=bw ram=p pc=pl ctrl=load; // fetch 
cpl6_ji : 

mdr=br mdr=low ram=bw ram=j j=pl; // MDR[7:0] <— RAM[j++] ; 

mdr=br mdr=high ram=bw ram=j j=pl; // MDR [15 : 8] <— RAM[j++] ; 

ram=br ram=i mdr=bw mdr=low i=pl; // RAM [i++] <— MDR[7 : 0] ; 

ram=br ram=i mdr=bw mdr=high i=pl; // RAM [i++] <— MDR[15 : 0] ; 

ir=aux ir=br ram=aux ram=bw ram=p pc=pl ctrl=load; // fetch 
jump : 

i=br pc=bw; // J <- PC 

pc=br pc=low ram=bw ram=i i=pl; // PC[7:0] < — RAM [i++] 

pc=br pc=high ram=bw ram=i i=ml; // PC [15 : 7] < — RAM[i — ] 

ir=aux ir=br ram=aux ram=bw ram=p pc=pl ctrl=load; 
j ump 8 c : 

mdr=br mdr=low ram=bw ram=p pc=pl; // MDR[7 : 0] < — RAM [pc++] 

mdr=br mdr=high ram=bw ram=p pc=pl; // MDR[15 : 7] < — RAM[pc++] 

pc=br sel=if_carry_8; // PC = (carry8?MDR:PC) 

ir=aux ir=br ram=aux ram=bw ram=p pc=pl ctrl=load; // fetch 
jump8nc : 

mdr=br mdr=low ram=bw ram=p pc=pl; // MDR[7:0] < — RAM [pc++] 

mdr=br mdr=high ram=bw ram=p pc=pl; // MDR[15 : 7] < — RAM[pc++] 

pc=br sel=if_not_carry_8 ; // PC = (not_carry8?MDR:PC) 

ir=aux ir=br ram=aux ram=bw ram=p pc=pl ctrl=load; // fetch 
j ump 8 z : 

mdr=br mdr=low ram=bw ram=p pc=pl; // MDR[7:0] < — RAM [pc++] 

mdr=br mdr=high ram=bw ram=p pc=pl; // MDR[15 : 7] < — RAM[pc++] 

pc=br sel=if_zero_8 ; // PC = (zero8?MDR:PC) 

ir=aux ir=br ram=aux ram=bw ram=p pc=pl ctrl=load; // fetch 



Version "C": 16-bit little-endian 



567 



jump8nz : 












mdr=br 


mdr=low ram=bw ram=p 


pc= 


=pl; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p 


pc= 


=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_not_zero_8 ; 








// PC = (not_zero8?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw 


ram= 


=p pc 


=pl 


ctrl=load; // fetch 


j ump 8 o : 












mdr=br 


mdr=low ram=bw ram=p 


pc= 


=pl; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p 


pc= 


=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_overf low_8 ; 








// PC = (overflow8?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw 


ram= 


=p pc 


=pl 


ctrl=load; // fetch 


jump 8 no : 












mdr=br 


mdr=low ram=bw ram=p 


pc= 


=pl; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p 


pc= 


=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_not_overf low_8 ; 








// PC = (not_overflow8?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw 


ram= 


=p pc 


=pl 


ctrl=load; // fetch 


j ump 8 n : 












mdr=br 


mdr=low ram=bw ram=p 


pc= 


=pl; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p 


pc= 


=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_negative_8 ; 








// PC = (negative8?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw 


ram= 


=p pc 


=pl 


ctrl=load; // fetch 


jump8nn : 












mdr=br 


mdr=low ram=bw ram=p 


pc= 


=pi; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p 


pc= 


=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_not_negative_8 ; 








// PC = (not_negative8?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw 


ram= 


=p pc 


=pl 


ctrl=load; // fetch 


j ump 16c: 












mdr=br 


mdr=low ram=bw ram=p 


pc= 


=pl; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p 


pc= 


=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_carry_l 6 ; 








// PC = (carryl6?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw 


ram= 


=p pc 


=pl 


ctrl=load; // fetch 


jumpl 6nc : 












mdr=br 


mdr=low ram=bw ram=p 


pc= 


=pi; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p 


pc= 


=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_not_carry_l 6; 








// PC = (not_carryl6?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw 


ram= 


=p pc 


=pl 


ctrl=load; // fetch 


j ump 1 6 z : 












mdr=br 


mdr=low ram=bw ram=p 


pc= 


=pl; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p 


pc= 


=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_zero_l 6; 








// PC = (zerol6?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw 


ram= 


=p pc 


=pl 


ctrl=load; // fetch 


jumpl 6nz : 












mdr=br 


mdr=low ram=bw ram=p 


pc= 


=pl; 




// MDR[7:0] < — RAM[pc++] 



568 



Version "C": 16-bit little-endian 



mdr=br 


mdr=high ram=bw ram=p pc=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_not_zero_l 6 ; 




// PC = (not_zerol6?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw ram=p pc 


=pl 


ctrl=load; // fetch 


jumpl 60 : 








mdr=br 


mdr=low ram=bw ram=p pc=pl; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p pc=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_overf low_l 6 ; 




// PC = (overflowl6?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw ram=p pc 


=pl 


ctrl=load; // fetch 


jumpl 6no : 








mdr=br 


mdr=low ram=bw ram=p pc=pl; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p pc=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_not_overf low_l 6; 




// PC = (not_overflowl6?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw ram=p pc 


=pl 


ctrl=load; // fetch 


jumpl 6n : 








mdr=br 


mdr=low ram=bw ram=p pc=pl; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p pc=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_negative_l 6 ; 




// PC = (negativel6?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw ram=p pc 


=pl 


ctrl=load; // fetch 


jumpl 6nn : 








mdr=br 


mdr=low ram=bw ram=p pc=pl; 




// MDR[7:0] < — RAM[pc++] 


mdr=br 


mdr=high ram=bw ram=p pc=pl; 




// MDR[15:7] < — RAM[pc++] 


pc=br 


sel=if_not_negative_l 6; 




// PC = (not_negativel6?MDR:PC) 


ir=aux 


ir=br ram=aux ram=bw ram=p pc 


=pl 


ctrl=load; // fetch 


call: 








i=br i 


=low ram=bw ram=p pc=pl sp=ml 


r 


// I [7:0] < — RAM[pc++], SP — 


i=br i 


=high ram=bw ram=p pc=pl sp=ml 


r 


// I [15: 7] < — RAM[pc++], SP — 


ram=br 


ram=s pc=bw pc=low sp=pl; 




// RAM[sp++] <- PC [7:0], SP++ 


ram=br 


ram=s pc=bw pc=high sp=ml; 




// RAM[sp — ] <- PC [15: 8], SP — 


pc=br 


i=bw; 




// PC <- I; 


ir=aux 


ir=br ram=aux ram=bw ram=p pc 


= P 1 


ctrl=load; // fetch 


call_i : 








sp=m2 ; 






// SP < — (SP - 2) 


ram=br 


ram=s pc=bw pc=low sp=pl; 




// RAM[sp++] <- PC [7:0], SP++ 


ram=br 


ram=s pc=bw pc=high sp=ml; 




// RAM[sp — ] <- PC [15: 8], SP — 


pc=br 


i=bw; 




// PC <- I; 


ir=aux 


ir=br ram=aux ram=bw ram=p pc 


= P 1 


ctrl=load; // fetch 


call_j : 








sp=m2 ; 






// SP < — (SP - 2) 


ram=br 


ram=s pc=bw pc=low sp=pl; 




// RAM[sp++] <- PC [7:0], SP++ 


ram=br 


ram=s pc=bw pc=high sp=ml; 




// RAM[sp — ] <- PC [15: 8], SP — 


pc=br 


j=bw; 




// PC <- J; 


ir=aux 


ir=br ram=aux ram=bw ram=p pc 


= P 1 


ctrl=load; // fetch 



Version "C": 16-bit little-endian 



569 



return : 
















pc=br 


oc=low 


ram=bw ram=s 


sp=pl; 






// PC [7:0] 


<- RAM[sp++] ; 


pc=br 


oc=high ram=bw ram=s 


sp=pl; 






// PC [15: 8] 


<- RAM[sp++] ; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


push8_i : 
















sp=ml ; 












// SP—; 




ram=br 


ram=s 


i=bw i=low; 








// RAM[sp] 


<- I[7:0]; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


push8_j : 
















sp=ml ; 












// SP—; 




ram=br 


ram=s 


j=bw j=low; 








// RAM[sp] 


<- J[7:0]; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


push8_a : 
















sp=ml ; 












// SP—; 




ram=br 


ram=s 


a=bw a=low; 








// RAM[sp] 


<- A[7:0]; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


push8_b : 
















sp=ml ; 












// SP—; 




ram=br 


ram=s 


b=bw b=low; 








// RAM[sp] 


<- B[7:0]; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


push8_bp : 
















sp=ml ; 












// SP—; 




ram=br 


ram=s 


bp=bw bp=low; 








// RAM[sp] 


<- BP [7:0] ; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


push8_mdr : 
















sp=ml ; 












// SP—; 




ram=br 


ram=s 


mdr=bw mdr=low 








// RAM[sp] 


<- MDR[7:0]; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


push8_f 1 : 
















sp=ml ; 












// SP—; 




ram=br 


ram=s 


fl=bw fl=low; 








// RAM[sp] 


<- FL[7:0]; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


pop8_i : 
















i=br i 


=low 


ram=bw ram=s sp 


=pl 






// I [7:0] < 


— RAM[sp++] ; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


pop8_j : 
















j=br j 


=low 


ram=bw ram=s sp 


=pl; 






// J[7:0] < 


— RAM[sp++] ; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


pop8_a : 
















a=br a 


=low 


ram=bw ram=s sp 


=pl; 






// A[7:0] < 


— RAM[sp++] ; 


ir=aux 


ir=br 


ram=aux ram=bw 


ram=p 


pc 


=pl 


ctrl=load; 


// fetch 


pop8_b : 

















570 



Version "C": 16-bit little-endian 



b=br b= 


=low ram=bw ram=s sp=pl; 




// B[7:0] < — RAM[sp++]; 


ir=aux 


ir=br 


ram=aux ram=bw ram=p pc ; 


=pl 


ctrl=load; // fetch 


pop8_bp : 










bp=br bp=low 


ram=bw ram=s sp=pl; 




// BP [7:0] < — RAM[sp++]; 


ir=aux 


ir=br 


ram=aux ram=bw ram=p pc= 


=pl 


ctrl=load; // fetch 


pop8_mdr : 










mdr=br 


mdr=low ram=bw ram=s sp=pl; 




// MDR[7:0] < — RAM[sp++] ; 


ir=aux 


ir=br 


ram=aux ram=bw ram=p pc= 


=pl 


ctrl=load; // fetch 


pop8_f 1 : 










fl=br fl=low 


ram=bw ram=s sp=pl; 




// FL[7:0] < — RAM[sp++]; 


ir=aux 


ir=br 


ram=aux ram=bw ram=p pc= 


=pl 


ctrl=load; // fetch 


pushl 6_i : 










sp=m2 ; 








// SP < — (SP - 2) 


ram=br 


rara=s 


i=bw i=low sp=pl; 




// RAM[sp++] <- I[7:0]; 


ram=br 


ram=s 


i=bw i=high sp=ml; 




// RAM[sp — J <- I [15: 8]; 


ir=aux 


ir=br 


ram=aux ram=bw ram=p pc= 


=pl 


ctrl=load; // fetch 


pushl 6_j : 










sp=m2 ; 








// SP < — (SP - 2) 


ram=br 


rara=s 


j=bw j=low sp=pl; 




// RAM[sp++] <- J[7:0]; 


ram=br 


ram=s 


j=bw j=high sp=ml; 




// RAM[sp — ] <- J [15: 8]; 


ir=aux 


ir=br 


ram=aux ram=bw ram=p pc ; 


=pl 


ctrl=load; // fetch 


pushl 6_a : 










sp=m2 ; 








// SP < — (SP - 2) 


ram=br 


ram=s 


a=bw a=low sp=pl; 




// RAM[sp++] <- A[7:0]; 


ram=br 


ram=s 


a=bw a=high sp=ml; 




// RAM[sp — J <- A [15: 8]; 


ir=aux 


ir=br 


ram=aux ram=bw ram=p pc ; 


=pl 


ctrl=load; // fetch 


pushl 6_b : 










sp=m2 ; 








// SP < — (SP - 2) 


ram=br 


ram=s 


b=bw b=low sp=pl; 




// RAM[sp++] <- B[7:0]; 


ram=br 


ram=s 


b=bw b=high sp=ml; 




// RAM[sp — ] <- B[15:8]; 


ir=aux 


ir=br 


ram=aux ram=bw ram=p pc= 


=pl 


ctrl=load; // fetch 


pushl 6_bp : 










sp=m2 ; 








// SP < — (SP - 2) 


ram=br 


ram=s 


bp=bw bp=low sp=pl; 




// RAM[sp++] <- BP [7:0]; 


ram=br 


ram=s 


bp=bw bp=high sp=ml; 




// RAM[sp — ] <- BP [15: 8] ; 


ir=aux 


ir=br 


ram=aux ram=bw ram=p pc= 


=pl 


ctrl=load; // fetch 


pushl 6_mdr 










sp=m2 ; 








// SP < — (SP - 2) 


ram=br 


ram=s 


mdr=bw mdr=low sp=pl; 




// RAM[sp++] <- MDR [7:0]; 


ram=br 


ram=s 


mdr=bw mdr=high sp=ml ; 




// RAM[sp — ] <- MDR [15: 8]; 


ir=aux 


ir=br 


ram=aux ram=bw ram=p pc= 


=pl 


ctrl=load; // fetch 


pushl 6_f 1 : 











Version "C": 16-bit little-endian 



571 



sp=m2 ; 






// SP < — (SP - 2) 


ram=br ram=s fl=bw fl=low sp=pl; 






// RAM[sp++] <- FL[7:0]; 


ram=br ram=s fl=bw fl=high sp=ml; 






// RAM[sp — ] <- FL[15:8] ; 


ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


popl 6_i : 








i=br i=low ram=bw ram=s sp=pl; 






// I [7:0] < — RAM[sp++] ; 


i=br i=high ram=bw ram=s sp=pl; 






// I [15:0] < — RAM[sp++] ; 


ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


popl 6_j : 








j=br j=low ram=bw ram=s sp=pl; 






// J [7:0] < — RAM[sp++] ; 


j=br j=high ram=bw ram=s sp=pl; 






// J [15:0] < — RAM[sp++] ; 


ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


popl 6_a : 








a=br a=low ram=bw ram=s sp=pl; 






// A[7:0] < — RAM[sp++] ; 


a=br a=high ram=bw ram=s sp=pl; 






// A[15:0] < — RAM[sp++]; 


ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


popl 6_b : 








b=br b=low ram=bw ram=s sp=pl; 






// B[7:0] < — RAM[sp++] ; 


b=br b=high ram=bw ram=s sp=pl; 






// B[15:0] < — RAM[sp++]; 


ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


popl 6_bp : 








bp=br bp=low ram=bw ram=s sp=pl; 






// BP [7:0] < — RAM[sp++]; 


bp=br bp=high ram=bw ram=s sp=pl; 






// BP [15:0] < — RAM[sp++] ; 


ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


popl 6_mdr : 








mdr=br mdr=low ram=bw ram=s sp=pl 


r 




// MDR[7:0] < — RAM[sp++] ; 


mdr=br mdr=high ram=bw ram=s sp=pl 


r 




// MDR[15:0] < — RAM[sp++] ; 


ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


popl 6_f 1 : 








fl=br fl=low ram=bw ram=s sp=pl; 






// FL[7:0] < — RAM[sp++]; 


fl=br fl=high ram=bw ram=s sp=pl; 






// FL[15:0] < — RAM[sp++] ; 


ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; // fetch 


c8tol 6u : 








a=br alu=bw alu=a alu=rank8 fl=br 


fl 


=aux // A[15:0] <- A[7:0], 


ir=aux ir=br ram=aux ram=bw ram= 


p 


pc= 


pi ctrl=load; // fetch; 


c8tol 6s : 








a=br alu=bw alu=a alu=rank8 alu=sign 


fl 


=br fl=aux // A[15:0] <- A[7 :0] , 


ir=aux ir=br ram=aux ram=bw ram= 


p 


pc= 


pi ctrl=load; // fetch; 


equal : 








a=br alu=bw alu=a alu=rankl6 fl=br 


fl=aux // A <- A, fetch 


ir=aux ir=br ram=aux ram=bw ram= 


P 


pc= 


pi ctrl=load; 


not : 









572 



Version "C": 16-bit little-endian 



a=br 


alu 


=bw 


alu=not alu=rankl6 fl=br fl=aux 


// A 


<- 


NOT A, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






and : 














a=br 


alu 


=bw 


alu=and alu=rankl6 fl=br fl=aux 


// A 


<- 


A AND B, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






nand : 














a=br 


alu 


=bw 


alu=nand alu=rankl6 fl=br fl=aux 


// A 


<- 


A NAND B, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






or : 














a=br 


alu 


=bw 


alu=or alu=rankl6 fl=br fl=aux 


// A 


<- 


A OR B, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






nor : 














a=br 


alu 


=bw 


alu=nor alu=rankl6 fl=br fl=aux 


// A 


<- 


A NOR B, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






xor : 














a=br 


alu 


=bw 


alu=xor alu=rankl6 fl=br fl=aux 


// A 


<- 


A XOR B, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






nxor : 














a=br 


alu 


=bw 


alu=nxor alu=rankl6 fl=br fl=aux 


// A 


<- 


A NXOR B, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






add : 














a=br 


alu 


=bw 


alu=add alu=rankl6 fl=br fl=aux 


// A 


<- 


A+B, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






sub : 














a=br 


alu 


=bw 


alu=sub alu=rankl6 fl=br fl=aux 


// A 


<- 


A-B, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






addc8 : 














a=br 


alu 


=bw 


alu=addc alu=rank8 fl=br fl=aux 


// A 


<- 


A+B+carry, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






subb8 : 














a=br 


alu 


=bw 


alu=subb alu=rank8 fl=br fl=aux 


// A 


<- 


A-B-borrow, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






addcl 6 : 














a=br 


alu 


=bw 


alu=addc alu=rankl6 fl=br fl=aux 


// A 


<- 


A+B+carry, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






subbl 6 : 














a=br 


alu 


=bw 


alu=subb alu=rankl6 fl=br fl=aux 


// A 


<- 


A-B-borrow, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






lshl8 : 














a=br 


alu 


=bw 


alu=lshl alu=rank8 fl=br fl=aux 


// A <- A «, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






lshr8 : 















Version "C": 16-bit little-endian 



573 



a=br 


alu 


=bw 


alu=lshr alu=rank8 fl=br fl=aux 


// A 


<- 


A », fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






ashl8 : 














a=br 


alu 


=bw 


alu=ashl alu=rank8 alu=sign fl=br 


f l=aux 




// A <- A*2, 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 




// fetch: 


ashr8 : 














a=br 


alu 


=bw 


alu=ashr alu=rank8 alu=sign fl=br 


f l=aux 




// A <- A/2, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






rotcl8 : 














a=br 


alu 


=bw 


alu=rotcl alu=rank8 fl=br fl=aux 


// A 


<- 


rotcl (A) , fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






rotcr 8 : 














a=br 


alu 


=bw 


alu=rotcr alu=rank8 fl=br fl=aux 


// A 


<- 


rotcr (A), fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






rotl8 : 














a=br 


alu 


=bw 


alu=rotl alu=rank8 fl=br fl=aux 


// A 


<- 


rotl (A) , fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






rotr8 : 














a=br 


alu 


=bw 


alu=rotr alu=rank8 fl=br fl=aux 


// A 


<- 


rotr (A) , fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






lshll6: 














a=br 


alu 


=bw 


alu=lshl alu=rankl6 fl=br fl=aux 


// A 


<- 


A «, fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






lshrl 6 : 














a=br 


alu 


=bw 


alu=lshr alu=rankl6 fl=br fl=aux 


// A 


<- 


A », fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






ashll6: 














a=br 


alu 


=bw 


alu=ashl alu=rankl6 alu=sign fl=br 


f l=aux 


// A <- A*2, 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 




// fetch; 


ashrl 6 : 














a=br 


alu 


=bw 


alu=ashr alu=rankl6 alu=sign fl=br 


f l=aux 


// A <- A/2, 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 




// fetch; 


rotcll6 : 














a=br 


alu 


=bw 


alu=rotcl alu=rankl6 fl=br fl=aux 


// A 


<- 


rotcl (A) , fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






rotcr 1 6 : 














a=br 


alu 


=bw 


alu=rotcr alu=rankl6 fl=br fl=aux 


// A 


<- 


rotcr (A), fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






rotll6 : 














a=br 


alu 


=bw 


alu=rotl alu=rankl6 fl=br fl=aux 


// A 


<- 


rotl (A) , fetch 


ir= 


aux 


ir= 


=br ram=aux ram=bw ram=p pc=pl Ctrl 


=load; 






rotrl 6 : 















574 



Version "C": 16-bit little-endian 





a=br alu=bw alu=rotr alu=rankl6 fl=t 


>r fl=aux // A <- rotr (A) , fetch 


in : 


ir=aux ir=br ram=aux ram=bw ram=p 


pc=pl ctrl=load; 




ioa=br ram=bw ram=p pc=pl; 


// IOA <- RAM[pc++]; 




ioc=req; 


// I/O request; 




ctrl=nop; 


// does not do anything 




a=br ioc=bw 


// A <- I/O, fetch; 




ir=aux ir=br ram=aux ram=bw ram=p 


pc=pl ctrl=load; 


out 








ioa=br ram=bw ram=p pc=pl; 


// IOA <- RAM[pc++] ; 




ioc=br a=bw; 


// I/O <- A 




ioc=req 


// I/O request, fetch; 




ir=aux ir=br ram=aux ram=bw ram=p 


pc=pl ctrl=load; 


if ack_jump : 






ioa=br ram=bw ram=p pc=pl; 


// IOA <- RAM[pc++] ; 




mdr=br mdr=low ram=bw ram=p pc=pl; 


// MDR[7:0] <- RAM[pc++] ; 




mdr=br mdr=high ram=bw ram=p pc=pl; 


// MDR[15:8] <- RAM[pc++] ; 




a=br ioc=bw ioc=isack; 


// A <- I/O is ack; 




a=br alu=a alu=rank8 alu=sign fl=br 


fl=aux; // A[15:0] <- A[7:0]; 




pc=br sel=if_not_zero_8 ; 


// PC = (not_zero8?MDR:PC) ; 




ir=aux ir=br ram=aux ram=bw ram=p pc 


=pl ctrl=load; // fetch 


int 








// push FL 






sp=m2 ; 


// SP < — (SP - 2) 




ram=br ram=s fl=bw fl=low sp=pl; 


// RAM[sp++] <- FL[7:0]; 




ram=br ram=s fl=bw fl=high sp=ml; 


// RAM[sp — ] <- FL[15:8] ; 




// reset interrupt enable flag, PC++ 




// (PC is incremented to jump the argument, before it is saved 




// inside the stack) . 






fl=br fl=aux alu=cleari pc=pl; 






// push PC 






sp=m2 ; 


// SP < — (SP - 2) 




ram=br ram=s pc=bw pc=low sp=pl; 


// RAM[sp++] <- PC [7:0] ; 




ram=br ram=s pc=bw pc=high sp=ml; 


// RAM[sp — J <- PC [15: 8] ; 




// push I 






sp=m2 ; 


// SP < — (SP - 2) 




ram=br ram=s i=bw i=low sp=pl; 


// RAM[sp++] <- I[7:0]; 




ram=br ram=s i=bw i=high sp=ml; 


// RAM[sp — J <- I [15: 8]; 




// Set the PC register back so that 


the argument 




// can be read. 






pc=ml ; 






// 





Version "C": 16-bit little-endian 



575 



i=br ivt=bw ivt=intb ram=bw ram=aux 


ram 


=p pc=pl; // J <- IVT <- RAM[pc++]; 


pc=br pc=low ram=bw ram=i i=pl; 






// PC [7:0] < — RAM[i++] 


pc=br pc=high ram=bw ram=i i=ml; 






// PC[15:7] < — RAM[i — ] 


// pop I 










i=br i=low ram=bw ram=s sp=pl; 






// 


I [7:0] < — RAM[sp++] ; 


i=br i=high ram=bw ram=s sp=pl; 






// 


I [15:0] < — RAM[sp++]; 


// fetch 










ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; 


iret : 










// pop PC 










pc=br pc=low ram=bw ram=s sp=pl; 






// PC [7:0] <- RAM[sp++] ; 


pc=br pc=high ram=bw ram=s sp=pl; 






// PC [15: 8] <- RAM[sp++] ; 


// pop FL 










fl=br fl=low ram=bw ram=s sp=pl; 






// FL[7:0] < — RAM[sp++]; 


fl=br fl=high ram=bw ram=s sp=pl; 






// FL[15:0] < — RAM[sp++]; 


// fetch 










ir=aux ir=br ram=aux ram=bw ram=p 


pc 


=pl 


ctrl=load; 


irq : 










// push FL 










sp=m2 ; 






// 


SP < — (SP - 2) 


ram=br ram=s fl=bw fl=low sp=pl; 






// RAM[sp++] <- FL [7:0]; 


ram=br ram=s fl=bw fl=high sp=ml; 






// RAM[sp — ] <- FL[15:8] ; 


// reset interrupt enable flag 










fl=br fl=aux alu=cleari; 










// Restore the PC correct value: 


PC 


is 


currently located after the 


// opcode of an instruction that 


is 


not 


currently executed, 


// because there is a hardware interrupt to serve; that is why the 


// correct value to save inside the 


stack is PC-1 . 


pc=ml ; 






// 


PC—; 


// push PC 










sp=m2 ; 






// 


SP < — (SP - 2) 


ram=br ram=s pc=bw pc=low sp=pl; 






// 


RAM[sp++] <- PC [7:0] ; 


ram=br ram=s pc=bw pc=high sp=ml; 






// 


RAM[sp — ] <- PC [15: 8] ; 


// push I 










sp=m2 ; 






// 


SP < — (SP - 2) 


ram=br ram=s i=bw i=low sp=pl; 






// 


RAM[sp++] <- I[7:0]; 


ram=br ram=s i=bw i=high sp=ml; 






// 


RAM[sp — ] <- I [15: 8]; 


// 










i=br ivt=bw ivt=inta; 






// 


I <- IVT <- IRQ; 


pc=br pc=low ram=bw ram=i i=pl; 






// 


PC [7:0] < — RAM[i++] 


pc=br pc=high ram=bw ram=i i=ml; 






// 


PC[15:7] < — RAM[i — ] 


// pop I 











576 



Version "C": 16-bit little-endian 



i=br i=low ram=bw ram=s 


sp=pl ; 


// I [7:0] < — RAM[sp++]; 


i=br i=high ram=bw ram=s 


sp=pl ; 


// I [15:0] < — RAM[sp++] ; 


// 






irq=done; 






// fetch 






ir=aux ir=br ram=aux ram= 


bw ram= 


p pc=pl ctrl=load; 


ivtl : 






i=br i=low ram=bw ram=p 


pc=pl ; 


// I [7:0] <- RAM[pc++ ] ; 


i=br i=high ram=bw ram=p 


pc=pl; 


// I [15: 8] <- RAM[pc++] ; 


ivt=br i=bw; 




// IVT <- MDR; 


ir=aux ir=br ram=aux ram= 


bw ram= 


p pc=pl ctrl=load; // fetch 


imrl : 






irq=br ram=bw ram=p pc=pl 




// IRQ <- RAM[pc++]; 


ir=aux ir=br ram=aux ram= 


bw ram= 


p pc=pl ctrl=load; // fetch 


cleari : 






fl=br fl=aux alu=cleari irq=done 


ir=aux ir=br ram=aux 


ram=bw 


ram=p pc=pl ctrl=load; 


seti : 






fl=br fl=aux alu=seti ire 


=done 




ir=aux ir=br ram=aux 


ram=bw 


ram=p pc=pl ctrl=load; 


clearc : 






fl=br fl=aux alu=clearc 






ir=aux ir=br ram=aux 


ram=bw 


ram=p pc=pl ctrl=load; 


setc : 






fl=br fl=aux alu=setc 






ir=aux ir=br ram=aux 


ram=bw 


ram=p pc=pl ctrl=load; 


cmp : 






fl=br fl=aux alu=sub 




// FL (A - B); 


ir=aux ir=br ram=aux 


ram=bw 


ram=p pc=pl ctrl=load; 


test : 






fl=br fl=aux alu=and 




// FL (A AND B) ; 


ir=aux ir=br ram=aux 


ram=bw 


ram=p pc=pl ctrl=load; 


inc_i : 






i=pl 




// I++, fetch; 


ir=aux ir=br ram=aux 


ram=bw 


ram=p pc=pl ctrl=load; 


inc_j : 






j=pl 




// J++, fetch; 


ir=aux ir=br ram=aux 


ram=bw 


ram=p pc=pl ctrl=load; 


inc_a : 






a=pl 




// A++, fetch; 


ir=aux ir=br ram=aux 


ram=bw 


ram=p pc=pl ctrl=load; 


inc_b : 







Version "C": 16-bit little-endian 



577 





b=pl 


















// B++, fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


inc_ 


-bp : 






















bp=pl 


















// BP++, fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


inc_ 


_sp : 






















sp=pl 


















// SP++, fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


inc_ 


_mdr : 






















mdr=pl 


















// MDR++, fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


inc_ 


.fl: 






















fl=pl 


















// FL++, fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


dec_ 


_i : 






















i=ml 


















// J — , fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


dec_ 


-j : 






















j=ml 


















// J — , fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


dec_ 


_a : 






















a=ml 


















// A — , fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


dec_ 


b: 






















b=ml 


















// B — , fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


dec_ 


-bp : 






















bp=ml 


















// BP — , fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


dec_ 


_sp : 






















sp=ml 


















// SP — , fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


dec_ 


mdr : 






















mdr=ml 


















// MDR — , fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


dec_ 


_fl: 






















fl=ml 


















// FL — , fetch; 




ir=aux 


ir= 


br 


ram= 


aux 


ram= 


=bw 


ram= 


=P 


pc=pl ctrl=load; 


// 






















stop : 






















ctrl=stop; 


















// stop clock 




//if resumed, 


fetch: 















578 



Version "C": 16-bit little-endian 



ir=aux ir=br ram=aux ram=bw ram=p pc=pl ctrl=load; 

// 

end 



10.11 Interrupts management 

There are three types of interrupts: those generated internally by the CPU, those gen- 
erated by the hardware (IRQ) and the software interrupts. Internal interrupts of the 
CPU can range from INTO to INT3, but currently there is only INTO which is related 
to the identification of a wrong opcode. The hardware interrupts can range from INT4 
to INT7 and match respectively the range IRQO to IRQ3. Software interrupts can 
range from INT8 to INT 15. The IVT table (interrupt vector table) must be prepared 
through the macrocode, which must initialize the IVT register with the address of the 
table location, as in the following example: 

begin macrocode @ 0 
jump #start 
nop 

interrupt_vector_table : 



. short 


0x0025 


// 


CPU 


# 


op_code_ 


error 




. short 


0x0024 


// 


CPU 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


CPU 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


CPU 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


IRQ 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


IRQ 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


IRQ 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


IRQ 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


software 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


software 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


software 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


software 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


software 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


software 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


software 


# 


default_ 


inter rupt_ 


routine 


. short 


0x0024 


// 


software 


# 


default_ 


inter rupt_ 


routine 



clef ault_interrupt_rout ine : 



Version "C": 16-bit little-endian 



579 





-j rpf 

J — 1_ ^3- I— 


Up OOU.t:_ 


J_ J_ U J! . 




O L- w k-^ 


S t 3.T t I 










1LLV O L IU L\ j O Or 




ivtl #interrupt_vector_table 




imrl OxflF // tutti 




seti 








.short 0x0080 


end 





The table might also be shorter, if there is no need for the software interrupts. 

The occurrence of an interrupt (CPU, hardware or software) involves the following: 
the FL register is saved on top of the stack, the interrupt enable flag is disabled, the 
PC register is saved on top of the stack. The iret instruction restores the PC and 
then the FL registers. But while the conclusion of an interrupt takes place always in 
the same way, through the description of the opcode iret, the start is different in the 
three cases. If it comes to interruption due to a wrong opcode, the microcode routine 
at the label op_error is performed; if it is a hardware interrupt, the microcode routine 
starting at the irq label is run, as specified by the dip-switch inside the control unit; 
if it is a software interrupt, the microcode routine starting at the int label is executed. 
The three situations are different: 

• The interrupt due to an incorrect opcode depends on an error from the code read 
inside the RAM memory, but it is not known the extent of this damage. Not being 
able to guess, the best choice for the routine associated to the interruption should 
coincide with the CPU halt, otherwise, it might be the case to try to ignore the 
wrong opcode and just try the next memory cell, without being able to know if 
there is possibly an argument to the wrong opcode just read. 

• The hardware interrupt (IRQ) occurs asynchronously with respect to the CPU ac- 
tivity and it is served only when the CPU itself would be ready to execute a new 



580 



Version "C": 16-bit little-endian 



opcode. In this condition, the PC register already points to the memory location 
next to the opcode that would have to be executed, so, before saving the PC reg- 
ister inside the stack, it is necessary to move back the PC one position: this way 
it points to the position of the opcode that must be executed after the interrupt is 
served. The microcode related to a hardware interrupt has also the task, once read 
the address matching the interrupt from the IVT table, to cancel the pending re- 
quest from the IRQ module. This is done by sending a signal through the control 
bus, which in the IRQ module is implemented as irq_done. It is then a task of the 
logic inside the IRQ module to know what is actually the IRQ signal to reset. At 
the same time, the IRQ module might require the management of another inter- 
rupt, but this management would be temporarily suspended, because the interrupt 
enable flag is disabled (it is disabled immediately after the FL register is saved 
on the stack). 

• The software interrupt is easier to manage, because it happens in a predictable 
way, without really interrupting the control unit activity. 

When an interruption occurs also exists the need to jump properly to the routine pro- 
vided in the IVT table. The IVT register has two separate inputs to receive the inter- 
rupt number to convert to memory address: one is connected to auxiliary bus, which 
is also connected to the BUS module and the RAM module; the other is connected 
to the IRQ module. When a CPU internal interrupt is generated, the IVT module is 
controlled directly by the control unit, through the BUS module; when a hardware 
interrupt is received, the IVT module is driven by the IRQ module; when it is a soft- 
ware interrupt, the IVT module receives the interrupt number from the RAM, as it is 
supplied as an argument to the opcode. It should also be noted that with the software 
interrupt, any interrupt number can be specified. 

10.12 Module "RTC": real time clock 

The RTC module (real time clock) produces one pulse per second through the hard- 
ware interrupt IRQO. If the IRQO is enabled inside the IRQ module, an INT4 is re- 
quested at every second. INT4 is translated into the fifth position inside the IVT table. 
The RTC module is described only by Verilog code: 



Version "C": 16-bit little-endian 581 



Listing 10.41. Module RTC. 



module RTC (T) ; 




output T ; 








R 1 Wr)V.S 




Id per i n 




d = 0 ; 




$ t kcr$wa.it 


(500) ; 


id = 1 : 




$ t kef $wait 


(500) ; 


end 




assign T = p; 




endmodule 





10.13 Module "TTY" 

The module TTY, for the management of the video-keyboard terminal, is almost the 
same as the previous version of the project: it adds an output connected to the signal of 
confirmation (acknowledge) of the keyboard, for controlling the signal IRQ1. In this 
way, when the user press a key on the keyboard, an interrupt IRQ1 is produced: the 
routine associated to the hardware interrupt can be used to execute the code necessary 
to handle what was typed. 



582 



Version "C": 16-bit little-endian 



Figure 10.42. Module tty. 



Only 8 bits of the I/O 
address are read 




S_DATA 




S_REQ 




S_ACK 


terminal 


K_DATA 




K_REQ 




K_ACK 


CLR 



Listing 10.43. Verilog code describing the module terminal. 

module terminal (K_DATA, K_REQ, K_ACK, S_DATA, S_REQ, S_ACK, CLR) ; 



output K_ACK; 
output S_ACK; 
output [7:0] K_DATA; 
input [7:0] S_DATA; 
input K_REQ; 
input S_REQ; 
input CLR; 
reg k_ready; 
reg [7:0] key; 



Version "C": 16-bit little-endian 583 



reg s_ready; 



initial 
begin 

k_ready = 0; 

s_ready = 0; 

key = 0 ; 
end 

always 
begin 

@ (posedge CLR) 
k_ready = 0; 
s_ready = 0; 
key = 0; 
end 

initial $tkg$post ("TERMINAL", "%m") ; 

always 
begin 

@ (posedge K_REQ) ; 

# 5; 

key = $tkg$recv ("%m.KD") ; 

# 5; 

k_ready = l'bl; 

# 5; 

@ (negedge K_REQ) ; 

# 5; 

k_ready = 1'bO; 
end 

always 
begin 

@ (posedge S_REQ) ; 

# 5; 



584 



Version "C": 16-bit little-endian 



$tkg$send ( "%m. SD", S_DATA) ; 

# 5; 

s_ready = l'bl; 

# 5; 

@ (negedge S_REQ) ; 

# 5; 

s_ready = 1'bO; 
end 



assign 
assign 
assign 



S_ACK = 
K_DATA = 
K ACK = 



s_ready; 

key; 
k_ready; 



endmodule 



Listing 10.44. File 'share/tkgate/vpd/terminal . tcl' for TCL interface. 

image create bitmap txtcurs -file "$bd/txtcurs .b" 

VPD :: register TERMINAL 
VPD::allow TERMINAL :: post 
VPD:: allow TERMINAL :: data 

namespace eval TERMINAL { 

# Public variables declarations: the variables $terminal_. . . 

# are arrays of which only the element $n is used; 

# that element identifies uniquely the working interface instance. 

variable terminal_w 
variable terminal_pos 
# 

variable KD 

# Function requested by TKGate to create the interface. 

proc post {n} { 

variable terminal_w 
variable terminal_pos 

# Create the window and save the object element in a $terminal_w array element . 

set terminal_w ($n) [VPD: : createWindow "TERMINAL $n" -shutdowncommand "TERMINAL :: impost $n"] 

# For convenience, copy the object reference inside the local 

§ variable $w; then, the variable $w will be used as a reference to the object . 

set w $terminal_w ( $n) 

text $w.txt -state disabled 

pack $w.txt 

# Put the cursor at the end of the displayed text . 

$w.txt image create end -image txtcurs 

# Bind the keyboard input, related to the object represented by 
§ $terminal_w ($n) , to the function sendChar. 



Version "C": 16-bit little-endian 



585 



bind $w <KeyPress> "TERMINAL: : sendChar $n \"%A\ n " 

# Open a reading channel, named «SD» (screen data), 

§ and associate it to the function «data»; moreover, open a 

# writing channel, named «KD» (keyboard data) . 

if {[info exists : :tkgate_islnitialized] } { 
VPD: :outsignal $n . KD TERMINAL :: KD ( $n) 

VPD : : insignal $n.SD -command "TERMINAL :: data $n" -format %d 

} 

# Reset the character count, used to count the characters displayed 

# on screen. 

set terminal„pos ( $n) 0 

} 

# Function that receives the typing and put it into the 

# channel «KD», related to the current interface instance. 

proc sendChar {n key} { 
variable KD 

if { [string length $key ] == 1 } { 
binary scan $key c c 
set TERMINAL: : KD ($n) $c 

} 

} 

# Function that TKGate requires to destroy the interface. 

proc unpost {n} { 

variable terminal_w 
variable terminal_pos 
destroy $terminal_w ($n) 
destroy $terminal_pos ($n) 
unset terminal__w ( $n) 
unset terminal_pos ( $n) 

} 

# Function used to get the data to display on screen. 

proc data {n c} { 

variable terminal_w 
variable terminal_pos 

# For convenience, copy the object reference representing the 
§ interface, inside the variable $w. 

set w $terminal_w ( $n ) 
catch { 

# The variable $c contains the character to display. 

if { $c == 7 } { 

# BEL 

bell 
return 

} elseif { $c == 127 | $c == 8 } { 

# DEL I BS 

if { $terminal_pos ($n) > 0 } { 

# Delete the last displayed character, but only if the 

# characters counter is greater than zero, otherwise 

# the cursor would disappear and the next characters 

# would be located in an unvisible screen area . 
$w.txt configure -state normal 

$w.txt delete "end - 3 chars" 



586 



Version "C": 16-bit little-endian 



$w.txt see end 

$w.txt configure -state disabled 

set terrainal_pos ($n) [expr {$terminal_pos ($n) - l}] 

} 

return 
} elseif { $c == 13 } { 
# Convert CR to LF. 

set c 10 

} 

# Convert the character number into a visible symbol . 

set x [format %c $c] 

# Display the symbol . 

$w.txt configure -state normal 
$w.txt insert "end - 2 chars" $x 
$w.txt see end 

$w.txt configure -state disabled 

# Update the displayed characters counter. 

set terminal_pos ( $n) [expr {$terminal_pos ($n) + l}] 

} 

} 

} 



10.14 Module "HDD" 

The HDD module is new compared to the previous version: it is an interface that sim- 
ulates a set of eight units of mass storage, each subdivided into sectors of 512 bytes. 
The device is accessed with different I/O addresses depending on the type of operation 
that is to be made. 



Version "C": 16-bit little-endian 
Figure 10.45. Module HDD. 



587 



hj/writ< 



O — D — p=0- 



iiilii h ^-. 

te M 



l>— o 



| gg= i 1 1 1 1 1 e i h ^h 

hd 6we I ^Ey* | )- 



>L>— O 



M "vie — )0 D- 




t + + 



=D- 



- D DR8 Q 

Ck C 



- D DR3 Q 

Ck 5 



D DR16 Q 

Ck c 



7^7 



D DR10Q 

Ck C 



D DR1 Q 

Ck C 



J 


Presel Q 


CIK 


JK 


K 


Q 

Clear 



REQ DATAJN 
DRIVE 
SECTOR 

hd 

BYTE 
WRITE 

ACK CLR DATA_0UT 



When a request is not yet sutisfied 
the value that can be read on the output 
is negative, because the most significant 
byte has all bit to one. 



V- 



Listing 10.46. Verilog code describing the module hd. 



module hd (DRIVE, SECTOR, BYTE, WRITE, DATA_IN, DATA_0UT, REQ, ACK, CLR); 

input [2:0] DRIVE; 

input WRITE, REQ, CLR; 

input [15:0] SECTOR; 

input [9:0] BYTE; 

input [7:0] DATA_IN; 

output [7:0] DATA_0UT; 

output ACK; 

// 

integer _data_out; 



588 



Version "C": 16-bit little-endian 



integer _ack; 
// 

reg [7:0] buf f er [ 0 : 1023 ] ; 

reg [8*24-1:0] filename = "hd0_sector_000000000 .mem" ; 
// 



integer 


i; 




integer 


sector_ 


_8 


integer 


sector_ 


1 


integer 


sector_ 


_6 


integer 


sector_ 


_5 


integer 


sector_ 


_4 


integer 


sector_ 


_3 


integer 


sector_ 


_2 


integer 


sector_ 


1 


integer 


sector_ 


_0 


integer 


x; 





// 

init ial 
begin 

for (i=0; i<1024; i=i+l) 
begin 
// 

// Initial buffer reset with 00. 

// 

buffer [i] = 8'h00; 
end 
_ack = 0; 
_data_out = 0; 
x = 0; 
end 

// 

always 
begin 

@ (posedge CLR) 

_ack = 0; 

_data_out = 0; 

x = 0; 
end 

// 
// 



Version "C": 16-bit little-endian 



589 



// 

always 
begin 
// 

// Start after a positive edge from REQ! . 

// 

@ (posedge REQ) ; 

# 10; 

// 

// Define the sector file name. 

// 

x = SECTOR; 
sector_0 = x%10; 
x = x/10; 
sector_l = x%10; 
x = x/10; 
sector_2 = x%10; 
x = x/10; 
sector_3 = x%10; 
x = x/10; 
sector_4 = x%10; 
x = x/10; 
sector_5 = x%10; 
x = x/10; 
sector_6 = x%10; 
x = x/10; 
sector_7 = x%10; 
x = x/10; 
sector_8 = x%10; 
// 

// The string starts from right to left ! 

// 

filename [12*8+7 : 12*8] = sector_8 + 8'd48; 
filename [11*8+7 : 11*8] = sector_7 + 8'd48; 
filename [10*8+7 : 10*8] = sector_6 + 8'd48; 



filename [9*8+7 


9*8] 


= sector_ 


_5 


+ 


8' d4 8 


filename [8*8+7 


8*8] 


= sector_ 


_4 


+ 


8' d4 8 


filename [7*8+7 


7*8] 


= sector_ 


_3 


+ 


8' d4 8 


filename [6*8+7 


6*8] 


= sector_ 


_2 


+ 


8' d4 8 


filename [5*8+7 


5*8] 


= sector. 


.1 


+ 


8' d4 8 



590 



Version "C": 16-bit little-endian 



filename [4*8+7 : 4*8] = sector_0 + 8'd48; 




// 




filename [21*8+7 : 21*8] = DRIVE + 8'd48; 




// 




if (WRITE) 




begin 




// 




// Put data inside the buffer. 




// 




buffer [BYTE] = DATA_IN; 




// 




// Save the buffer to disk. 




// Please remember that $writememh() 


must be enabled inside 


// TKGate configuration! 




// 




$writememh ( filename, buffer); 




// 




// Return the same data read. 




// 




_data_out = buffer [BYTE] ; 




end 




else 




begin 




// 




// Get data from disk to the buffer. 




// 




$readmemh (filename, buffer); 




// 




// Return the data required. 




// 




_data_out = buffer [BYTE] ; 




end 




// 




// Acknowledge. 




// 




_ack = 1; 




// 




// Wait the end of request (the negative 


edge) 


// before restarting the loop. 




// 





Version "C": 16-bit little-endian 



591 



@ (negedge REQ) ; 

# 10; 

// 

// Now become ready again . 

// 

_ack = 0; 
end 
// 

assign DATA_0UT = _data_out; 

assign ACK = _ack; 

// 

endmodule 



Since this is a new module, it is important to describe the behavior of the hd module, 
which has just been shown as a Verilog source: the inputs DRIVE, SECTOR and 
BYTE are used to uniquely identify a byte, belonging to a certain sector of a certain 
storage device. In practice, each virtual storage unit is divided into sectors, from the 
first, equal to zero, to the last, equal to 65536. Since the sector size is 512 bytes, these 
storage unit have virtually a maximum capacity of 32 Mbyte. 

The input WRITE allows to select a write access to the device storage, otherwise a 
read access is intended. The access to the unit is one byte at a time and the output 
DATA_OUT should be used for reading, while the input DATA_IN should be used 
for writing. The inputs and outputs REQ, ACK and CLR operate in a predictable 
manner, in accordance with what is already described in the case of terminal device 
(keyboard and screen). 

To use the HDD device, it is necessary to provide the coordinates of the byte to which 
the access should be done, writing to the I/O ports 4, 5 and 6, respectively for the 
storage unit, the field and the byte. Then it is possible to ask a read access (I/O address 
2) or write access (I/O address 3). When a read or write operation has been completed, 
the confirmation signal (acknowledge) is issued from the HDD module and sent to the 
IRQ module, as a IRQ2 signal. Anyway, it is not necessary to enable IRQ2 to access 
the HDD module, because reading is always possible, with the difference that if the 
read data is not yet valid, the value is negative. Similarly, after writing, it is possible 
to verify the write completion through a read of the same byte: if the value obtained 
is negative, it means that the operation is not yet complete. 

The module hd allows to use the virtual storage devices without the need to first 



592 



Version "C": 16-bit little-endian 



create files: when accessing for the first time, in writing, to an area that had never 
been used before, the file that represents the sector is created on the fly (the file is 
created inside the directory where TKGate is working). If it is read a sector that does 
not exist already, it is produced just a null value (00i 6 ) without creating the associated 
file. The files that are created on writing match the pattern 'hdw_sector _sssssssss . 
mem'. 

10.15 Macrocode: terminal usage example, through interrupts 

The following code performs the reading of the keyboard, through the interruption 
generated by the keyboard itself, and the representation of the text typed on the screen. 
The begin of code defines the location of the IVT table and the associated code for 
the various table elements. 

Listing 10.47. Macrocode managing a terminal through the keyboard interrupts. 

begin macrocode @ 0 
jump #start 
nop 

interrupt_vect or_t able : 



. short 


OxOOlC 


// 


CPU 


. short 


OxOOlC 


// 


CPU 


. short 


OxOOlC 


// 


CPU 


. short 


OxOOlC 


// 


CPU 


. short 


OxOOlC 


// 


IRQ 


. short 


OxOOlE 


// 


IRQ keyboard 


. short 


OxOOlC 


// 


IRQ 


. short 


OxOOlC 


// 


IRQ 


. short 


OxOOlC 


// 


software 


. short 


OxOOlC 


// 


software 


. short 


OxOOlC 


// 


software 


. short 


OxOOlC 


// 


software 



def ault_interrupt_rout ine : 

iret 
op_code_error : 

stop 
keyboard : 

in 1 // Keyboard read. 

equal 



Version "C": 16-bit little-endian 



593 



jump 8 z # keyboard end 


// Exit if no data was read. 


OUL u 


/ / L/uflGJ-WlSG pj.iniZ OH SCJ.GGI2 UUG 




// same vai ue. 


jump #keyboard 


// LiOOp . 


keyboard_end : 




i ret 




start : 




loaflio ffaaua i 


// oet c/je svacK ±ocavion . 


mxr S-MPIT5 S-CP 
II1V 75iyiUt\ r ^or 








ivtl #interrupt vector. 


_t aoie 


imrl UxUi 


// iRQs are enabled. 


OCL1 




keyboard reset : 




in 1 


/ / /s.ej'JDOa ira react . 


ec[ual 




jump8nz #start 


// Loop until the keyboard buffer 




// is empty. 


endless_cycle : 




j unip ffKiiuicbfa Lytic 


/ / . Ti i o ^ 7 « tf<^ 
/ / c/Uo L. J. UUp i \J 1. GvG 1. . 


stop : 


// Will never reach this point. 


stop 




aata_(J : 




. short 0 




QdL d. ± . 




.short 0x0080 




end 





594 



Version "C": 16-bit little-endian 



Figure 10.48. Keyboard input and screen output. Video: ogv http://www.youtube. 
com/watch ?v=dgIfZHNTedM 




,, I Li i 

0020 

:, M, 
I ■ I ■ 

0090 

, 

0070 

, , , 



61 2a 00 00 Id 00 lc 00 

lc 00 lc 00 lc 00 lc 00 

d2 64 29 00 Cl 00 €1 le 

00 rS Of If cO 01 A, 69 

80 00 XX XX XX XX XX XX 



lc OO lc 00 lc 00 1* 00 

lc 00 lc 00 5d II CO 01 

00 9d 4a 40 00 39 60 04 

2a 00 61 la 00 ff 00 00 



E XX 27 00 3d OO U VI 



View and modily the 
contents ol a RAM or ROM 
component. Select 



Last Read Access 

Address: 007c 
Dala: B'hSa 
Time: 672.318us 



Last Write Access 

Address: 007b 
Data: B'hO 
Time: 666 78us 



r-i 



. I H i l l _ " ■■ M I. l '| 



Dismiss 



595 

Version "D" 



Chapter 11 



11.1 General purpose registers 598 

11.1.1 Module "RANK" 601 

11.1.2 Modules "D_select" and "Q_select" 601 

11.2 Module "VRw" 602 

11.3 Module "RAM" 605 

1 1 .4 Module "ALU" and related submodules 608 

11.5 Module "BUS" 615 

11.6 Module "IRQ" 616 

11.7 Modules "Dw" 617 

11.8 Module "IVT" 618 

11.8.1 Module "DRw" 619 

1 1 .9 Module "RTC": real time clock 619 

11.10 Module "TTY" 621 

11.11 Module "HDD" 625 

11.12 Module "CTRL" 630 

11.12.1 Modules "Fw" 633 

1 1 . 12.2 Module "CLK_CLR" 634 

11.13 Memory and microcode fields 636 

11.14 Opcodes 641 

11.15 Microcode 671 

11.16 Macrocode 728 



This is another version of the project, with more powerful registers and a better 
control-unit. There are two data-busses, each one connected with a different ALU 



596 



Version "D" 



input, but at the moment, the opcode is still reduced to 8 -bit and there is no space 
for enough instructions, so the ALU continues to depend on registers A and B. The 
old SEL module is not present anymore because the selection work is done inside 
the control-unit. The MDR register is not present for this version; instead there is a 
temporary register TMP and a new C register, used as accumulator. 

This version does not access the memory correctly, as some previous version do; this 
fact is evidenced by a lot of warning produced by the TKGate simulation. The next 
version "M" has a different memory management, with a new MDR register, but it is 
very slow compared with the current version. 



Attachments 


Description 


attachments/xcpu/xcpu-d. v 


TKGate Verilog netlist source file. 


attachments/xcpu/xcpu-d.gm 


TKGate microcode and macrocode source 
file. 


attachments/xcpu/xcpu-d-terminal.vpd. 
tcl 


TCL/Tk script related to the terminal mod- 
ule TTY. 



Version "D" 



597 



Figure 11.2. Simple CPU, version "D": two data-busses and an accumulator reg- 
ister. 



bus A bus B 




53::S8 



69; H 



85: '0 



:86 16 



117:10216 



0* 
'2 



16 

T^A HDD 



IOA — 
IRQ2 — 

c ~ 

c — 

IOA — 
K * 



io_address 



IRQ2 



RTC 
IRQO 



c B 

D t 

(IR) 
C A 








** 
















c B 

C 

T 

S RAM (, 
J (ram) 

I 

P A 


S, 
i 


1£ 


-/■ 

*l 


3 

3:04 




' / -> 


+> 




*> 

4 
/ 

16 






c B 

D t 

(PC) 
C A 














+■ 






c B 
D t 
c <" „ 








+■ 








«** 






c B 
D t 
C A 




+> 


















c B 

D t 

r (SP) . 
C A 








+* 


+> 










c B 

D t 

(IMP) 
C A 
l 4 




++ 

















Is Q c 
IRQ 



!5 , c 



iRQpr 

3 
2 



la c f^" 

IVT D 3 

3 



(IOA) 



BUS 



A 






16 




C 




t 
B 


(BP) 


D 


2 




c 










16 








A 




C 




t 

B 


(B) 


D 


2 




c 










16 


A 








C 




t 

B 


(A) 


D 






c 





A 


B 


Fo 






ALU C 


Fi 


Q 



158:150 



i* A alu C 



149:134 



4 



(C) 



16 

□ 4 



256 

250:247 



ft. 0 " 
-off 



246 244 

1:0 



243 241 
240 225 



190:175 

1:0 
174:159 



1:0 



598 



Version "D" 



« 



11.1 General purpose registers 

The registers are made in a similar way as the previous version, but internally there 
are new modules that can be incremented or decremented without restrictions, before 
or after reading the register. There are two types of registers: the following figure 
shows the two external layouts. 

Figure 11.3. 16-bit registers: external appearance. 



Q 
c 

c 

Q 
C 
Q 
c 

C n 

r 

v -'15:12 



bus select: 0-A; 1-B 

bus write 

load byte BO: 7:0 

load byte Bl: 15:8 

byte selection: 0-BO; 1-B1 

rank: 0-8-bit; 1-16-bit 

signed: O-unsigned; 1 -signed 

pre— increment: -8.. +7 

pre-increment update 

post-increment: -S..+7 



connection to the "A " bus 



D register content copy 



^ test for debugging 



c o clear 
c \ clock 





t 






4- 


c 


D 


c 




C D 


c 








/ -► 


alu 




A 


t 


B 




A 


t 






% 


t 


4- 



<^ M i5:o connection from the ALU 



^15:0 connection to the "B" bus 



Version "D" 

Figure 11.4. 16-bit registers: internal structure. 



599 



D L 

Cqo 

Cdo VR8 

gk p 
t 



c 




L 


qil 


Cqo 




qi 


Cdo 


VR8 


di 
Cqi 




k 


P 


Cdi 
C 



± 



Qi 

Q select 



byte 





Do 




D_select 


Byte 


Di 



In 






rank 


RANK 




sign 


Out 





16 



pre_inc_upd ate 
prejnc 





Out 


sign 


RANK 


rank 






In 




—C3= 



0 1 



V 



<c 



The C and FL registers are made with a slightly different module, where the "B" bus 
connection is named alu and is only able to receive data. 



600 



Version "D" 



Figure 11.5. Alternative 16-bit registers structure. 



4 



D L 

Cqo 

Cdc VR8 



|-vl|Q3 Ul|.p.|W 



D 


L qil 


Cqo 


qi 


Cdo 


VR8 _ d ! 

Cqi 






Odi 




k 


P C 



D *H- 



Qi 

Q_select 

Qo 



Byte 



byte 



Byte 



Do 

D_seleot 

Di 



In 




RANK 


rank 


Out 


sign 



prejn :_update 



15:12 

H 

10:7 





Out 


sign 


RANK 


rank 






In 



v- 



5 

4 

3:2 

1 

0 



<c 



V 



,'4 

v 



A 
alu 



The control line C4 {byte selection) should be zero when C5 {rank) is equal to one (16- 
bit); otherwise, it is used to select the byte: when writing to the bus, the selected byte 
from the register is written to the bus (to the lower bus side); when reading from the 
bus, the lower byte from the bus is stored to the selected register byte. The following 
sections show the modules responsible for the rank reduction and the byte selection. 



Version "D" 



601 



11.1.1 Module "RANK" 

Figure 1 1.6. Rank reduction module: the module rank and its submodules. 



« 



sign >~ 







'l6 


In 

RANK 


rank 


j 0 


7 






sign 






Out 


1 1 


15 









Di 

RNK16 
Do 



x>- 



~< rank 



x>- 



Di 

v 



0 1 



Di 
V 



|« RNK16 



Di 

RNK8 i [r 1 
Do 



Di 

RNK8 r fr- 1 
Do 



/ 16 
Do 



RNK8 



<r 



2 



v 

Do 

1 1 .1 .2 Modules "D_select" and "Q_select" 

The incoming byte selection module (D_select), when Byte is equal to zero, does 
not change the output, so that Do is equal to Di. When Byte is equal to one, the low 
input byte is replicated to the high output byte; that is: Do is equal to Di 7:0 -2 S +Di 7:0 . 
This alteration is used only to copy the byte received from the bus to the selected 
position inside the register. 

The outgoing byte selection (module Q_select) is used to select from the register a 
byte to be written to the data-bus. When Byte is equal to zero, there is no change to 
the output. When Byte is equal to one, the byte Di 15 ; 8 is copied to the byte Do 7.0 (Do 
= Di 15:8 -2*+Di 15:8 ). The module rank does the rest of the work, cleaning the most 
significant byte or setting it if the value is negative and is to be treated as a signed 
value. 



602 



Version "D" 



Figure 11.7. Left side: incoming byte selection. Right side: outgoing byte selec- 
tion. 







Do 




D_select 


Byte 


Di 


t 



Di 

V 



/ 



16 



I 1 

00 o 



/ , 



°8 



0 



16 



v 

Do 



<Byte 



Qi 

V 

/16 



I I 

00 o 

in r-^ 





Qi 




Q_select 


Byte 


Qo 





1 0 



16 



V 



Qo 



<Byte 



The most important module inside the general purpose register is VR8 {versatile reg- 
ister), which is a 8-bit data register, shown inside the figures of the following section. 



« 



11.2 Module "VRw" 

The module VRw is « -bit register that allows to add a value, positive or negative, 
before reading the register or after reading it. In particular, if the value is added before 
reading, the register might not be updated with it, when the clock signal reaches the 
edge. 



Version "D" 



603 



Figure 11.8. Module VR8: how it works. 

L load control line 



i n data to be loaded 

: -^15:0 



qil load pre-incremented value after clock edge 



i pre— increment value 





D L qil 
Cqo qi 

Cdo VR8 c d q | 

Q Cdi 
Ck p C 






post-increment value 




4_ ;G?/ pre-increment carry-in \ 


[Cdi post-increment carry-out i 4- 

....... «- 




Cdi post-increment carry-in i 


g i5 register output 


t t t 





clock signal (positive edge) 



C 0-> clear: set output to 00000000 



P 0 => preset: set output to 11111111 

It all starts from module VR1 which is made of a D flip-flop and two full adders, as 
shown in the following figure. 



604 



Version "D" 



Figure 11.9. Module VR1. 



Cdo <£- 



post adder 

FA 

'43 



-<di 

-<Cdi 



D 

v 



pre add load qii>- 



0 1 



p 

v 



0 1 



Cqo < 



pre adder 



'43 



FA 



V 



"<qi 
<Cqi 



<L load 











P 




Q 




D 


Q 




Ck 




C 





<Ck 



A 
c 



V 

Q 

Two modules VR1 make a module VR2; two modules VR2 make a module VR4 and so 
on. 



Version "D" 



605 



Figure 11.10. Modules VR2 and VR4. 



v 



D 

Cqo 



Cdo 



Ck F 



L qil 

qi ; 

VR1 _ di . : 

Cqi - 

n - ; 

a p c 



V oil 




A 
C 



2 

^<qi 



^ — <di 



-<Cqi 
-<Cdi 



Cqo *< — 
Cdo 



v 



D 

Cqo 



Cdo 



A 
Ck 



A 
P 



qil 

VR2 _ di . 
Cqi 

Sik p c 



V qil 



□ L qil 
Cqo qi 

VR2 J 1 ! 
Cqi 

Cdi 
k P C 



Cdo 



A 
c 



<q, 



^ — <di 



-< Cqi 



11.3 Module "RAM" 

The module RAM is similar to the previous version of the project. In particular, there is 
now the ability to receive an address from the TMP register and, when the memory is 
written, there are two added D latches (modules DH8) which hold the data read from 
the bus. 



606 



Version "D" 



Figure 11.11. The RAM module. 



P = register PC 
I = register I 
J = register J 
S = register SP 
T = register TMP 



index_regisler 




control 



6 



■<C 



Modules DHw are the same as the previous version, starting from a controlled NAND 
SR latch, which becomes a D latch, as the following figure shows. 



Version "D" 



607 



Figure 1 1.12. The steps from the SR latch to the DH4 module. 



module E (enable) 



p >- 
s>- 

E>- 
R>- 

C >- 



> 



> 



> 



D 

V 



module DH1 

p >- 




> Q 



^ Q 



P > 



C > 



H > 



D 

V 



/2 



I 1 

1- o 



module DH2 



p > 



c >- 



H >" 



D H 




DH1 Q 


H C 





D 

V 



/A 



/ 



D P 




DH2 Q 


H C 






/2 



module DH4 



Q 




Q 



608 



Version "D" 



« 



1 1.4 Module "ALU" and related submodules 

The module ALU, is similar to the previous version; the most important difference 
is that there is a single set of ALU status flags: carry, zero, negative, overflow. The 
ALU module contains the same module rank already seen inside the general purpose 
registers. 

Figure 11.13. Module ALU. 



CO: sign 
C1 : rank: 0=i 



C[8:6]=0: LOGIC 
C[8:6]=1:ADD, SUB 
C[8:6]=2: SHIFT, ROTATE CARRY 
C[8:6]=3: ROTATE 
C[8:6]=4: FLAG SET-RESET 

LOGIC 

C[4:2]=0:q = a 
C[4:2]=1:q = aANDB 
C[4:2]=2:q = aORb 
C[4:2]=3:q = aXORb 
C[4:2]=4:q = NOT (a XOR b) 
C[4:2]=5:q = NOT (aORb] 
C[4:2]=6: q = NOT (a AND b) 
C[4:2]=7:q = NOTa 

ADD, SUB 
C2: subtract 
C3: use previous carry 

SHIFT 

C2: shift right 
C3: arithmetic shift 
C4: use previous carry 

ROTATE 
C2: rotate right 

FLAG SET-RESET 
C5=0: selected flag reset 
C5=1 : selected flag activation 
C[4:2]=0: carry 
C[4:2]=1:zero 
C[4:2]=2: negative 
C[4:2]=3: overflow 
C[4:2]=4: interrupt enable 
C[4:2]=5: not used 
C[4:2]=6: not used 
C[4:2]=7: not used 




The other components inside the ALU module are just the same as the previous ver- 
sion. 



Version "D" 



609 



Figure 11.14. Module LOGIC: the logic unit. 



C=0: q = a 
C=1:q = aAND B 
C=2: q = a OR b 
C=3: q = a XOR b 
C=4: q = NOT (a XOR b) 
C=5: q = NOT (a OR b) 
C=6: q - NOT (a AND b) 
C=7: q - NOT a 




V 

Q 



Figure 11.15. Module AS: addition and subtraction 



carry out 
borrow out 



B 

V 



16 



16 




0 



V V 

Co16 016 



V 



A B 

Co FA8 ci 

o 



subtract 



3 



carry_in_used 



overflow 



V v 



Co8 08 



-<c 



<Ci 

carry in 
borrow in 



610 



Version "D" 



Figure 11.16. Modules fa«: «-bit full adder. 



Co 



A 

V 



module FA1 



full adder 



9 

V 



-o 



-a 



V 
s 



module FA4 



Co <- 



O < 



B 

V 



A 

V 



/4 



<Ci 



Co < 
o ^ 



/2 



/T2 



A 


B 


Co 


FA1 Ci 


0 


S 



B 

V 



/4 



A 


B 




A 


B 


Co 


FA2 Ci 


+■ 


<- 


Co 


FA2 Ci 


0 


s 




<- 


0 


s 



A B 
Co FA1 Ci 
0 



-i o 

I I 



V 



-<Ci 



<Ci 



■ G.C2 



s 



Version "D" 

Figure 11.17. Module SH: bit shift. 



0 



0 



v 

Co16 



/ 


) 


\ 




/ 


'18 



la 


D 


lr 


Lo 




SH8 


Li 


Ri 






Ro 


O 




S 



arithmetic 



rank 



la 


D 


lr 


Lo 




Li 


Ri 


SH8 


Ro 




O 




S 



sh_left_and_carry_li :ft_8 



V 

016 



v 

s 



V 

08 



□ 



use_previous_carry 



■o 



-<Ci 



sh_righ t_and_carry_ri ght 



V 

Co8 



612 



Version ™D' 



Figure 11.18. Module ROT: bit rotation. 



A 

V 



/ 16 



I I 

00 o 

Co 



I 



la 


D 


lr 


Lo 




Li 


Ri 


SH8 


Ro 




O 




S 



right 



rank 



rank 



r 



la 


D 


lr 


Lo 




Li 


Ri 


SH8 


Ro 




0 




S 



2 



-<c 



bo o 



The modules SHw are one-bit logic or arithmetic shifter. It all starts from module SHI, 
as the following figure shows. 



Version "D" 



613 



Figure 11.19. Module SHw: one-bit logic or arithmetic shift. 



D 

V 



left-out 



Ri>" 



right— in 



[1] 



r 



o 



la> 

0=logic shift 
1=arithmetic shift 



la 

V 



D 

V 



left-in 



<Li 

> Ro 

right-out 





' 2 







module SH2 



module SHI 



[2] 



[1] Arithmetic shift conditions: 

- the requested shift is arithmetic; 

- the requested shift is to the right; 

- the most significant bit value is one. 
[2] Overflow conditions: 

- the requested shift is arithmetic; 

- the requested shift is to the left; 

- the most significant bit value is changed. 



<lr 

0=shift left 
1=shift right 



Lo <" 



Ri>- 



la 


D 


lr 


Lo 


SH1 


Li 


Ri 




Ro 


0 




S 



la D 

Lo 



I 3 



D 

V 



module SH4 



Lo <■ 
Ri>" 



la 


D 


lr 




Lo 


SH2 


Li 




<- 


Ri 




Ro 




-► 


0 




S 







lr 

V 



Li 



SH1 

Ri Ro 

O S 



lr 

v 



+ 






+ 


la 


D 


lr 


Lo 






Li 




SH2 






Ri 




Ro 


0 




S 







ro o 
J 



V 4 



o 



-<Li 
> RO 



— <Li 
> Ro 



614 



Version "D" 



Figure 11.20. Module fsr: flags set-reset. 




/ 


'16 




'i 6 




1 




0 





v 

Fo 



Version "D" 



615 



11.5 Module "BUS' 



« 



The module BUS is used to let the control unit to put a value inside the data-bus. This 
module BUS is almost the same as the previous version: only the connection names to 
the bus are changed and the control line used to select the destination bus. 



Figure 11.21. Module BUS. 



bus select 



c> 



18 



bus write 




B A 



616 



Version "D" 



« 



11.6 Module "IRQ" 

The IRQ module is just the same as the previous version, but here is connected to 
the A data-bus. All the details about the module functionality should be found at the 
previous version description. 

Figure 11.22. Module IRQ. 



irq_register 



Q D1 

0 » CK 



irq_mask_register 



X 



■ irq_clear 



Q Q 
C D4 p 

Ck D 



irq_priority 




is irq_set 



irq_to_int 



0000— > 0100 
0001 — > 0100 
0010— > 0101 
0100— > 0110 
1000— > 0111 




hardware interrupt: 01 .. 



0 

A 



Version "D" 

11.7 Modules "Dn 



The modules Dw are D flip-flops, in paralel, as the following figure shows. 

Figure 11.23. Building Dn modules. 

module Dl 
(Dflip-flop) 




v 

Q 



: 




\ 


i 






/ 





module D2 









P 


Q 


D 




D1 


0 






c Ck 



A 
c 



Q P D 
D1 

Q g Ck 



-<Ck 





P 




Q 


D 

D2 


Q 


c 


Ck 



A 
c 



module D4 



■Q P D 
D2 

■Q g Ck 



618 



Version "D" 



« 



11.8 Module "IVT" 

The ivt module is just the same as the previous version, but here is connected to 
the A data-bus. All the details about the module functionality should be found at the 
previous version description. 

Figure 11.24. Module ivt. 

la lb 

V V 



clock 



2 



clear 



IVT start address 



Ck 



DR16 l 



Q 



interrupt_select 



ZTT 



interrupt 



"1 



^16 



16 

Merrupt_x_2 



A B 
Co FA16 Ci 
O e 



16 



load 



V- 



D 



bus_write 



7^<C 



V 



0 

A 



V 



Version "D" 

11.8.1 Module "DRw" 

The modules IRQ and ivt use modules DRw, which are w-bit data registers. 
Figure 11.25. Building DR/z modules. 

D 

V 





' 2 







module DR2 



D 

V 



module DR1 



Q <r 









P 


Q 




D1 ° 


Q 




c Ck 



Ck>- 
-<L 

C >- 





D 


Ck 


DR1 l 


C 


Q 







D 


Ck 


DR1 l 


C 


Q 





-<Ck 



D 

V 



-l o 

I I 



V 



A 

c 



module DR4 

Ck> 



C > 




<L 



619 



« 



<L 



Q 



620 



Version "D" 



1 1 .9 Module "RTC": real time clock 

The RTC module (real time clock) is just the same as the previous version: it generates 
a 1 Hz impulse, producing the hardware interrupt IRQO. All the details about the 
module functionality should be found at the previous version description. 



Listing 11.26. Module RTC: Verilog declaration. 



module RTC (T) ; 




output T; 




req p; 




always 




begin 




P = 0; 




$tkg$wait 


(500) ; 


p = 1; 




$tkg$wait 


(500) ; 


end 




assign T = p; 




endmodule 





Version "D" 



621 



11.10 Module TTY" 

The TTY module is just the same as the previous version: it is a textual screen- 
keyboard terminal interface. All the details about the module functionality should 
be found at the previous version description. 

Figure 11.27. Module TTY. 



« 



Only the first 8 bits are read 
from the I/O device address, 




Listing 11.28. Module terminal: Verilog code. 



module terminal (K_DATA, K_REQ, K_ACK, S_DATA, S_REQ, S_ACK, CLR) ; 



output K_ACK; 
output S_ACK; 
output [7:0] K_DATA; 
input [7:0] S_DATA; 
input K_REQ; 



622 



Version "D" 



input S_REQ; 
input CLR; 
reg k_ready; 
reg [7:0] key ; 
reg s_ready; 

initial 
begin 

k_ready = 0; 

s_ready = 0; 

key = 0 ; 
end 

always 
begin 

@ (posedge CLR) 
k_ready = 0; 
s_ready = 0; 
key = 0; 
end 

initial $tkg$post ("TERMINAL", "%m") ; 

always 
begin 

@ (posedge K_REQ) ; 

# 5; 

key = $t kg$ recv ( " %m . KD " ) ; 

# 5; 

k_ready = l'bl; 

# 5; 

@ (negedge K_REQ) ; 

# 5; 

k_ready = 1'bO; 
end 

always 



Version "D" 



623 



begin 

@ (posedge S_REQ) ; 

# 5; 

$tkg$send ( "%m. SD", S_DATA) ; 

# 5; 

s_ready = l'bl; 

# 5; 

@ (negedge S_REQ) ; 

# 5; 

s_ready = 1'bO; 
end 



assign 
assign 
assign 



S_ACK = 
K_DATA = 
K ACK = 



s_ready; 

key; 
k_ready; 



endmodule 



Listing 11.29. File 'share/tkgate/vpd/terminal . tcl' for TCL interface. 

image create bitmap txtcurs -file "$bd/txtcurs .b" 

VPD :: register TERMINAL 
VPD::allow TERMINAL :: post 
VPD:: allow TERMINAL :: data 

namespace eval TERMINAL { 

# Public variables declarations: the variables $terminal_. . . 

# are arrays of which only the element $n is used; 

# that element identifies uniquely the working interface instance. 

variable terminal_w 
variable terminal_pos 
# 

variable KD 

# Function requested by TKGate to create the interface. 

proc post {n} { 

variable terminal_w 
variable terminal_pos 

# Create the window and save the object element in a $terminal_w array element . 

set terminal_w ($n) [VPD: : createWindow "TERMINAL $n" -shutdowncommand "TERMINAL :: impost $n"] 

# For convenience, copy the object reference inside the local 

# variable $w; then, the variable $w will be used as a reference to the object . 

set w $terminal_w ( $n ) 

text $w.txt -state disabled 

pack $w.txt 



624 



Version "D" 



# Put the cursor at the end of the displayed text . 

$w.txt image create end -image txtcurs 

# Bind the keyboard input, related to the object represented by 
§ $terminal_w ($n) , to the function sendChar. 

bind $w <KeyPress> "TERMINAL :: sendChar $n \"%A\"" 

# Open a reading channel, named «SD» (screen data), 

# and associate it to the function «data»; moreover, open a 

# writing channel, named «KD» (keyboard data) . 

if {[info exists : :tkgate_islnitialized] } { 
VPD: :outsignal $n.KD TERMINAL :: KD ( $n) 

VPD : : insignal $n.SD -command "TERMINAL :: data $n" -format %d 

} 

# Reset the character count, used to count the characters displayed 

# on screen. 

set terminal_pos ( $n) 0 

} 

# Function that receives the typing and put it into the 

# channel «KD», related to the current interface instance. 

proc sendChar {n key} { 
variable KD 

if { [string length $key ] == 1 } { 
binary scan $key c c 
set TERMINAL: : KD ($n) $c 

} 

} 

# Function that TKGate requires to destroy the interface. 

proc unpost {n} { 

variable terminal_w 
variable terminal_pos 
destroy $terminal_w ($n) 
destroy $terminal_pos ($n) 
unset terminal_w ( $n) 
unset terminal__pos ( $n) 

} 

# Function used to get the data to display on screen. 

proc data {n c} { 

variable terminal_w 
variable terminal_pos 

# For convenience, copy the object reference representing the 

# interface, inside the variable $w. 

set w $terminal_w ($n) 
catch { 

# The variable $c contains the character to display. 

if { $c == 7 } { 

# BEL 

bell 
return 

} elseif { $c == 127 | $c == 8 } { 

# DEL I BS 

if { $terminal_pos ($n) > 0 } { 

# Delete the last displayed character, but only if the 

# characters counter is greater than zero, otherwise 



Version "D" 



625 



# the cursor would disappear and the next characters 
§ would be located in an unvisible screen area . 

$w.txt configure -state normal 
$w.txt delete "end - 3 chars" 
$w.txt see end 

$w.txt configure -state disabled 

set terrainal_pos ( $n) [expr {$terminal_pos ( $n) - l}] 

} 

return 
} elseif { $c == 13 } { 
# Convert CR to LF. 

set c 10 

} 

# Convert the character number into a visible symbol . 

set x [format %c $c] 

# Display the symbol . 

$w.txt configure -state normal 
$w.txt insert "end - 2 chars" $x 
$w.txt see end 

$w.txt configure -state disabled 

# Update the displayed characters counter. 

set terminal_pos ( $n) [expr {$terminal_pos ($n) + l}] 

} 

} 

} 



11.11 Module "HDD 



The HDD module is just the same as the previous version: it is a simulated mass- 
memory drive whith the ability to handle eight units. All the details about the module 
functionality should be found at the previous version description. 



626 



Version "D" 



Figure 11.30. Module HDD. 



=E> 



f>HD- 



3D—D- 



=d- 



r=0 



2:0 3 



□ DR8 q 

Ck 5 



1 



L 

D DR3Q 
Ck C 



L 

d DR16q 

Ck C 



dDR10q 

Ck C 



D DR1 q 

Ck C 



Vdd 



Ck JK_ 
K r. 0 



REQ 
DRIVE 
SECTOR 
B\TE 
WRITE 



ACK CLR DATA_OUT 



When a request is not yet satisfied, the 
value that can be read at the output is 
negative, because the most significant byte 
has all bits set to one. 



Listing 11.31. Verilog code describing the module hd. 



module hd (DRIVE, SECTOR, BYTE, WRITE, DATA_IN, DATA_OUT, REQ, ACK, CLR); 

input [2:0] DRIVE; 

input WRITE, REQ, CLR; 

input [15:0] SECTOR; 

input [9:0] BYTE; 

input [7:0] DATA_IN; 

output [7:0] DATA_OUT; 

output ACK; 

// 



Version "D" 



627 



integer _data_out; 


integer _ack; 




// 




reg [7:0] buff er [ 0 : 1023 ] ; 


reg [8*24-1:0] filename = "hd0_sector_000000000 .mem" ; 


// 




integer i; 




integer sector_8 




integer sector_7 




integer sector_6 




integer sector_5 




integer sector_4 




integer sector_3 




integer sector_2 




integer sector_l 




integer sector_0 




integer x; 




// 




initial 




begin 




for (i=0; i<1024; i=i+l) 


begin 




// 




// Initial buffer reset with 00. 


// 




buffer 


[i] = 8'h00; 


end 




_ack = 0; 




_data_out = 


= 0; 


x = 0; 




end 




// 




always 




begin 




@ (posedge CLR) 


_ack = 0; 




_data_out = 


= 0; 


x = 0; 




end 




// 





628 



Version "D" 



// 
// 

always 
begin 
// 

// Start after a positive edge from REQ! . 

// 

@ (posedge REQ) ; 

# 10; 

// 

// Define the sector file name. 

// 

x = SECTOR; 
sector_0 = x%10; 
x = x/10; 
sector_l = x%10; 
x = x/10; 
sector_2 = x%10; 
x = x/10; 
sector_3 = x%10; 
x = x/10; 
sector_4 = x%10; 
x = x/10; 
sector_5 = x%10; 
x = x/10; 
sector_6 = x%10; 
x = x/10; 
sector_7 = x%10; 
x = x/10; 
sector_8 = x%10; 
// 

// The string starts from the right side and continues 
// to the left! 

// 

filename [12*8+7 : 12*8] = sector_8 + 8'd48; 
filename [11*8+7 : 11*8] = sector_7 + 8'd48; 
filename [10*8+7 : 10*8] = sector_6 + 8'd48; 
filename [9*8+7 : 9*8] = sector_5 + 8'd48; 
filename [8*8+7 : 8*8] = sector_4 + 8'd48; 
filename [7*8+7 : 7*8] = sector_3 + 8'd48; 



Version "D" 



629 



filename [6*8+7 : 6*8] = sector_2 + 8'd48; 




filename [5*8+7 : 5*8] = sector_l + 8'd48; 




filename [4*8+7 : 4*8] = sector_0 + 8'd48; 




// 




filename [21*8+7 : 21*8] = DRIVE + 8'd48; 




// 




if (WRITE) 




begin 




// 




// Put data inside the buffer. 




// 




buffer [BYTE] = DATA_IN; 




// 




// Save the buffer to disk. 




// Please remember that $writememh() 


must be enabled inside 


// TKGate configuration! 




// 




$writememh ( filename, buffer); 




// 




// Return the same data read. 




// 




_data_out = buffer [BYTE] ; 




end 




else 




begin 




// 




// Get data from disk to the buffer. 




// 




$readmemh (filename, buffer); 




// 




// Return the data required. 




// 




_data_out = buffer [BYTE] ; 




end 




// 




// Acknowledge. 




// 




_ack = 1; 




// 




// Wait the end of request (the negative 


edge) 



630 



Version "D" 



// before restarting the loop. 

// 

@ (negedge REQ) ; 

# 10; 

// 

// Now become ready again . 

// 

_ack = 0; 
end 
// 

assign DATA_0UT = _data_out; 

assign ACK = _ack; 

// 

endmodule 



11.12 Module "CTRL" 

The module CTRL is more complex than the previous version, because the conditional 
jumps are now managed inside the control module and because that requires the abil- 
ity to jump inside the microcode execution. 



Version "D" 

Figure 11.32. Module CTRL. 



631 



interrupt set 



Is in :orrupt_o nablc 



r 1 " 



irq: 0xlC2 



£ D Ck 

hfp D1 _c 

Q 5 



R> i 



clock_pulse 



clock counter 



\± rt — 

^ Ti Ck 
H»P F16 o 



flag_selecled 

jump_tru8 



irq_rouline_address 



microcode Jump 



□ L qil 
" Cqo 1 



(NIPC, a 
Tik P C 

^PP A j_ 



3^" 



MPC: microprogram counter 



/I 



condition_select 



V V 



The microprogram counter, MPC, is made with a module VR10, but connected in 
the way that it is incremented at every positive clock edge. The MPC can load a 
new address when load line is activated, or when the jumpjrue line is active. The 
microcode Jump line contains a microcode address to jump to, when jumpjrue is 
active. The condition _select line contains a number, representing the condition to be 
checked, so that, if true, will activate the line jumpjrue . 



632 



Version "D" 



Figure 11.33. Module Ctrl: microcode load selection. 



interrupt set ^ 



FL 

V 



V 

map 



lsinterrupt_enable 



□ 



"D 

5? 



2:0 



r* 



1C2 



D Ck 
> D1 c 
Q Q 



/4 



0/ 



3 not 



flag_selected 

\J~^ jumpjrue 



jump_to_irq 



,0 1 



10 



irq_routine_address 



,0 1 




clock 



/I0 r 



D 


L 


qil . 


Cqo 




qi 


Cdo 

Q 
Ck 


VR10 


di 


(MPC) 
P 


Cqi 
Cdi 

c 



pp 



A- 



clear 



10 
10 



PP 



A 



10 



A 

condition select 



▼ 

microcode address 



load 

microcodejump 



The previous figure shows the detail of the upper side, where there is the selection 
control of the microcode address to load inside the MPC. The microcode address 
might come: 

• from the map memory, as a translation of the opcode into microcode address; 

• from the dip-switch containing the address of the microcode procedure necessary 



Version "D" 



633 



to handle a hardware interrupt (IRQ); 
• from the line microcode Jump . 

When no other special conditions are present and the line load is active, the register 
MPC loads the value obtained from the map memory. If a hardware interrupt was 
previously received while hardware interrupts were allowed, it is stored inside the 
D flip-flop on the right. Then, when the control unit tries to load the next opcode 
address, it loads the interrupt procedure address instead. The condition _select and 
the microcode Jump lines are controlled by the microcode: this way the jump that is 
selected is done only if the condition results true, otherwise, there is no jump and the 
register MPC is simply incremented to the next microinstruction. 

The control unit contains also the clock generator and a frequency divisor, as de- 
scribed in the following sections. 

11.12.1 Modules Tw" 

The modules Fn are frequency divisors, made with T flip-flop, as the following figures 
show. 

Figure 1 1.34. Modules Dl and Tl: building a T flip-flop from a D flip-flop. 



module Dl: positive edge D flip-flop 



V 



p > 



Ck>- 



D>- 



C >- 



> Q 



Q < 



Q <^ 



> Q 



module Tl: T flip -flop 



Q m d 

Q £ Ck 



A 
C 



A 
Ck 



« 



634 



Version "D" 



« 



Figure 11.35. Building the Fn modules. 
module Fl 



To ' 



Q 



-a 



p 

V 



Q P T 
T1 

Q q Ck 



module F2 



Q < / 



p 

v 



-<Ti 



-<Ck 



To < 











P 




Q 




Ti 


To 


F1 


Ck 






C 





A 
c 




Q 



1:0 



3:2 



2 



A 
C 



P 

V 



To < 





+ 


Q 


P 

F2 


Ti 


To 


C 




Ck 









Q 


P 


Ti 




To 


F2 


Ck 






C 





module F4 

— <Ti 

1 <Ck 



A 
C 



-<Ti 



-<Ck 



11.12.2 Module XLK_CLR" 

The module clk_CLR is responsible for the clock pulse generation and for the reset 
line, which is to be synchronized with the clock. The clock frequency may be con- 
trolled by the dip-switch at the top. It is important to remind that the control unit 
receives an inverted clock pulse, because the microcode data should be ready before 
the clock positive edge. 



Version "D* 



635 



Figure 11.36. Module clk_clr. 



0 -2,5 MHz 

1 -1,25 MHz 

2 -625 kHz 

3 -320 kHz 

4 -160 kHz 

5 -80 kHz 



6 -40 kHz 

7 -20 kHz 
8-10 kHz 

9 -5 kHz 

10 -2,5 kHz 

11 -1,25 kHz 



12 -625 Hz 

13 -320 Hz 

14 - 160 Hz 

15 - 80 Hz 




3* Clk 



> 



-<Rst 



D 



> CIr 



F0 - 5 MHz 

Highest frequency allowed, to prevent triggering undesired oscillations inside 
the T flip-flop chain, used to divide the frequency. 



Figure 11.37. Module one_up, used to start the oscillation inside the module 

CLK CLR. 



module one_up #(.W(1000)) (Z); 
output Z; 
reg Z; 



initial 
begin 

Z = 1'bO; 

$tkg$wait (W) ; 

Z = l'bl; 
end 



endmodule 



636 



Version "D" 



11.13 Memory and microcode fields 

The memory for this version of the project are described by the following lines of 
TKGate code. There are many blocks of memory for the microcode word, because 
every component connected to the data-bus can be controlled independently. 



Listing 11.38. Memory banks description for TKGate. 



map 


bank 


[9:0] 


ctrl 


. map ; 


microcode 


bank 


[31 : 


0] 


Ctrl 


. microO ; 


microcode 


bank 


[63 : 


32] 


ctrl 


. microl ; 


microcode 


bank 


[95 : 


64] 


ctrl 


. micro2 ; 


microcode 


bank 


[127 


: 96] 


ctrl 


. micro3 ; 


microcode 


bank 


[159 


: 128] 


ctrl 


. micro4 ; 


microcode 


bank 


[191 


: 160] 


ctrl 


. micro5 ; 


microcode 


bank 


[223 


: 192] 


ctrl 


. micro6; 


microcode 


bank 


[255 


: 224] 


ctrl 


. micro7 ; 


macrocode 


bank 


[15 : 


0] 


ram . 


ram; 



Listing 11.39. Fields of the microcode word, for TKGate. 

field ctrl [1:0] = {nop=0, stop=l, load=2}; 

field jump[5:2] = {false=0, carry_t=l, zero_t=2, negative_t=3, 

overf low_t=4 , irq_enabled_t=5 , true=6, 
carry_f=9, zero_f=10, negat ive_f =1 1 , 
overf low_f =12 , irq_enabled_f =13 }; 

field addr[15:6] = {ciao=0}; 

// 

field ir[31:16] = {select_bus_a=0 , select_bus_b=l , bus_write=2, 

register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
qpl=0x0080, qp2=0x0100, qp3=0x0180, qp4=0x0200, 
qp5=0x0280, qp6=0x0300, qp7=0x0380, qm8=0x0400, 
qm7=0x0480, qm6=0x0500, qm5=0x0580, qm4=0x0600, 
qm3=0x0680, qm2=0x0700, qml=0x0780, qup=0x0800, 
dpl=0xl000, dp2=0x2000, dp3=0x3000, dp4=0x4000, 
dp5=0x5000, dp6=0x6000, dp7=0x7000, dm8=0x8000, 
dm7=0x9000, dm6=0xA000, dm5=0xB000, dm4=0xC000, 
dm3=0xD000, dm2=0xE000, dml=0xF000 }; 



Version "D" 



637 



// 

field ram [37: 32] = {select_bus_a=0 , select_bus_b=l , bus_write=2, 

load=4, p=0, i=8, j=16, s=24, t=32}; 

// 

field pc[53:38] = {select_bus_a=0 , select_bus_b=l , bus_write=2, 

register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
qpl=0x0080, qp2=0x0100, qp3=0x0180, qp4=0x0200, 
qp5=0x0280, qp6=0x0300, qp7=0x0380, qm8=0x0400, 
qm7=0x0480, qm6=0x0500, qm5=0x0580, qm4=0x0600, 
qm3=0x0680, qm2=0x0700, qml=0x0780, qup=0x0800, 
dpl=0xl000, dp2=0x2000, dp3=0x3000, dp4=0x4000, 
dp5=0x5000, dp6=0x6000, dp7=0x7000, dm8=0x8000, 
dm7=0x9000, dm6=0xA000, dm5=0xB000, dm4=0xC000, 
dm3=0xD000, dm2=0xE000, dml=0xF000 }; 
field i[69:54] = {select_bus_a=0 , select_bus_b=l , bus_write=2, 

register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
qpl=0x0080, qp2=0x0100, qp3=0x0180, qp4=0x0200, 
qp5=0x0280, qp6=0x0300, qp7=0x0380, qm8=0x0400, 
qm7=0x0480, qm6=0x0500, qm5=0x0580, qm4=0x0600, 
qm3=0x0680, qm2=0x0700, qml=0x0780, qup=0x0800, 
dpl=0xl000, dp2=0x2000, dp3=0x3000, dp4=0x4000, 
dp5=0x5000, dp6=0x6000, dp7=0x7000, dm8=0x8000, 
dm7=0x9000, dm6=0xA000, dm5=0xB000, dm4=0xC000, 
dm3=0xD000, dm2=0xE000, dml=0xF000 }; 
field j [85:70] = {select_bus_a=0 , select_bus_b=l , bus_write=2, 

register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
qpl=0x0080, qp2=0x0100, qp3=0x0180, qp4=0x0200, 
qp5=0x0280, qp6=0x0300, qp7=0x0380, qm8=0x0400, 
qm7=0x0480, qm6=0x0500, qm5=0x0580, qm4=0x0600, 
qm3=0x0680, qm2=0x0700, qml=0x0780, qup=0x0800, 
dpl=0xl000, dp2=0x2000, dp3=0x3000, dp4=0x4000, 



638 



Version "D" 



dp5=0x5000, dp6=0x6000, dp7=0x7000, dm8=0x8000, 
dm7=0x9000, dm6=0xA000, dm5=0xB000, dm4=0xC000, 
dm3=0xD000, dm2=0xE000, dml=0xF000 }; 
field sp[101:86] = {select_bus_a=0 , select_bus_b=l , bus_write=2, 

register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
qpl=0x0080, qp2=0x0100, qp3=0x0180, qp4=0x0200, 
qp5=0x0280, qp6=0x0300, qp7=0x0380, qm8=0x0400, 
qm7=0x0480, qm6=0x0500, qm5=0x0580, qm4=0x0600, 
qm3=0x0680, qm2=0x0700, qml=0x0780, qup=0x0800, 
dpl=0xl000, dp2=0x2000, dp3=0x3000, dp4=0x4000, 
dp5=0x5000, dp6=0x6000, dp7=0x7000, dm8=0x8000, 
dm7=0x9000, dm6=0xA000, dm5=0xB000, dm4=0xC000, 
dm3=0xD000, dm2=0xE000, dml=0xF000 }; 
field tmp [ 117 : 102 ] = {select_bus_a=0 , select_bus_b=l , bus_write=2, 

register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
qpl=0x0080, qp2=0x0100, qp3=0x0180, qp4=0x0200, 
qp5=0x0280, qp6=0x0300, qp7=0x0380, qm8=0x0400, 
qm7=0x0480, qm6=0x0500, qm5=0x0580, qm4=0x0600, 
qm3=0x0680, qm2=0x0700, qml=0x0780, qup=0x0800, 
dpl=0xl000, dp2=0x2000, dp3=0x3000, dp4=0x4000, 
dp5=0x5000, dp6=0x6000, dp7=0x7000, dm8=0x8000, 
dm7=0x9000, dm6=0xA000, dm5=0xB000, dm4=0xC000, 
dm3=0xD000, dm2=0xE000, dml=0xF000 }; 
field fl [133:118] = {select_bus_a=0 , select_bus_b=l , bus_write=2, 

register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
qpl=0x0080, qp2=0x0100, qp3=0x0180, qp4=0x0200, 
qp5=0x0280, qp6=0x0300, qp7=0x0380, qm8=0x0400, 
qm7=0x0480, qm6=0x0500, qm5=0x0580, qm4=0x0600, 
qm3=0x0680, qm2=0x0700, qml=0x0780, qup=0x0800, 
dpl=0xl000, dp2=0x2000, dp3=0x3000, dp4=0x4000, 
dp5=0x5000, dp6=0x6000, dp7=0x7000, dm8=0x8000, 



Version "D" 



639 



dm7=0x9000, dm6=0xA000, dm5=0xB000, dm4=0xC000, 
dm3=0xD000, dm2=0xE000, dml=0xF000 }; 
field c [14 9: 134] = {select_bus_a=0 , select_bus_b=l , bus_write=2, 

register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 

rank_8=0, rank_16=32, unsigned=0, signed=64, 



qpl 


=0x0080, 


qp2 


=0x0100, 


qp3 


=0x0180, 


qp4 = 


0x0200, 


qp5 


=0x0280, 


qp6 


=0x0300, 


qp7 


=0x0380, 


qm8= 


0x0400, 


qm7 


=0x0480, 


qm6 


=0x0500, 


qm5 


=0x0580, 


qm4 = 


0x0600, 


qm3 


=0x0680, 


qm2 


=0x0700, 


qml 


=0x0780, 


qup= 


0x0800, 


dpi 


=0x1000, 


dp 2 


=0x2000, 


dp 3 


=0x3000, 


dp4 = 


0x4000, 


dp 5 


=0x5000, 


dp 6 


=0x6000, 


dp 7 


=0x7000, 


dm8= 


0x8000, 


dm 7 


=0x9000, 


dm 6 


=0xA000, 


dm5 


=0xB000, 


dm4 = 


OxCOOO, 


dm3 


=0xD000, 


dm2 


=0xE000, 


dml 


=0xF000 


u 





// 

field alu[158:150] = {unsigned=0, signed=l, rank_8=0, rank_16=2, 

a=0, and=4, or=8, xor=12, 
nxor=16, nor=20, nand=24, not=28, 
add=64, sub=68, addc=72, subb=76, 
lshl=128, lshr=132, ashl=136, ashr=140, 
rotcl=144, rotcr=148, 
rotl=192, rotr=196, 

clearc=256, clearz=260, clearn=264, 
clearo=268, cleari=272, 
setc=288, setz=292, setn=296, 
seto=300, seti=304}; 

// 

field a [174: 159] = {select_bus_a=0 , select_bus_b=l , bus_write=2, 

register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
qpl=0x0080, qp2=0x0100, qp3=0x0180, qp4=0x0200, 
qp5=0x0280, qp6=0x0300, qp7=0x0380, qm8=0x0400, 
qm7=0x0480, qm6=0x0500, qm5=0x0580, qm4=0x0600, 
qm3=0x0680, qm2=0x0700, qml=0x0780, qup=0x0800, 
dpl=0xl000, dp2=0x2000, dp3=0x3000, dp4=0x4000, 
dp5=0x5000, dp6=0x6000, dp7=0x7000, dm8=0x8000, 
dm7=0x9000, dm6=0xA000, dm5=0xB000, dm4=0xC000, 



640 



Version "D" 



field b [190 : 175] 



field bp[206:191] 



// 

field bus [224 : 207] 
// 

field ioa[240:225] 



dm3=0xD000, dm2=0xE000, dml=0xF000 }; 
{select_bus_a=0 , select_bus_b=l , bus_write=2, 
register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
qpl=0x0080, qp2=0x0100, qp3=0x0180, qp4=0x0200, 
qp5=0x0280, qp6=0x0300, qp7=0x0380, qm8=0x0400, 
qm7=0x0480, qm6=0x0500, qm5=0x0580, qm4=0x0600, 
qm3=0x0680, qm2=0x0700, qml=0x0780, qup=0x0800, 
dpl=0xl000, dp2=0x2000, dp3=0x3000, dp4=0x4000, 
dp5=0x5000, dp6=0x6000, dp7=0x7000, dm8=0x8000, 
dm7=0x9000, dm6=0xA000, dm5=0xB000, dm4=0xC000, 
dm3=0xD000, dm2=0xE000, dml=0xF000 }; 
{select_bus_a=0 , select_bus_b=l , bus_write=2, 
register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
qpl=0x0080, qp2=0x0100, qp3=0x0180, qp4=0x0200, 
qp5=0x0280, qp6=0x0300, qp7=0x0380, qm8=0x0400, 
qm7=0x0480, qm6=0x0500, qm5=0x0580, qm4=0x0600, 
qm3=0x0680, qm2=0x0700, qml=0x0780, qup=0x0800, 
dpl=0xl000, dp2=0x2000, dp3=0x3000, dp4=0x4000, 
dp5=0x5000, dp6=0x6000, dp7=0x7000, dm8=0x8000, 
dm7=0x9000, dm6=0xA000, dm5=0xB000, dm4=0xC000, 
dm3=0xD000, dm2=0xE000, dml=0xF000 }; 

{bw=0xl0000, select_bus_a=0, select_bus_b=0x20000}; 

{select_bus_a=0 , select_bus_b=l , bus_write=2, 
register_load_byte_l=4 , register_load_byte_2=8 , 
register_load=12 , 

select_byte_l=0 , select_byte_2=l 6, 
rank_8=0, rank_16=32, unsigned=0, signed=64, 
pl=128, p2=256, p3=384, p4=512, 
p5=640, p6=768, p7=896, 

m8=1024, m7=1152, m6=1280, m5=1480, m4=1536, 
m3=1664, m2=1792, ml=1920, update=2048}; 



// 



Version "D" 



641 



field 


ivt [243 


241] 


= {bus_wr it e=l , ivt_load=2, 

select_int_a=0 , select_int_ 


b=4}; 




// 












field 


irq[246 


244] 


= {bus_wr it e=l , irq_mask_load= 


2, irq_ 


_done=4}; 


// 












field 


ioc [250 


247] 


= {load=l, bus_write=2, req=4, 


isack= 


=8}; 



11.14 Opcodes 

For the opcodes are used only eight bits and all available combinations are specified. 
The following table shows the opcode organization. 

Table 11.40. Opcodes. 



« 



0x60 
0x68 
0x70 
0x78 
0x80 
0x81 
0x82 
0x84 
0x86 
0x88 



0x00 


00 


0x40 


010000. . 


0x44 


010001. . 


0x48 


010010. . 


0x4C 


0100110. 


0x4E 


0100111. 


0x50 


010100. . 


0x54 


010101. . 


0x58 


010110. . 


0x5C 


0101110. 


0x5E 


0101111. 



01100. . . 
01101. . . 
OHIO. . . 
01111. . . 

10000000 
10000001 
1000001. 
1000010. 
1000011. 
1000100. 



byteO 



byte 1 



byte 2 



b7 


b6 


b5 


b4 


b3 


b2 


b1 


bO 




cp % % 


% 


% 


cp n % 


A, B, I, J 


const16 


cp (%) % 


(I, J) 


A, B 




cp % (%) 


A, B 


(I, J) 


cp n (%) 


(I, J) 


const16 


cp (%) (%) 


(I, J) 






cp8 n % 


A, B, I, J 


const8 




cp8 (%) % 


(I, J) 


AB 






cp8 % (%) 


A, B 


(I, J) 


cp8 n (%) 


(I, J) 


const8 




cp8 (%) (%) 


(I, J) 






byte 0 


byte 1 byte 2 


b7 


b6 


b5 


b4 


b3 


b2 


b1 


bO 




push % 


% 


push8 % 


% 


pop % 


% 


pop8 % 


% 


push n 


const16 


push8 n 


const8 




push (%) 


(I, J) 






push8 (%) 


(I, J) 




pop (%) 


(I, J) 


pop8 (%) 


(I, J) 



byte 3 



byte 3 



642 



0x90 
0x98 
0x9A 
0x9C 
0x9E 
OxAO 
0xA2 
0xA4 
0xA6 
0xA8 
OxAA 



Ox AC 
OxAE 
OxBO 
0xB2 
0xB4 
0xB6 
0xB8 



OxBC 
OxBE 
OxCO 
0xC2 
0xC4 
0xC6 
0xC8 
OxCA 
OxCC 
OxCE 



OxDO 
0xD2 
0xD4 
0xD6 
0xD8 
OxDA 
OxDC 



10010. . . 
1001100. 
1001101. 
1001110. 
1001111. 
1010000. 
1010001. 
1010010. 
1010011. 
1010100. 
1010101. 



1010110. 
1010111. 
1011000. 
1011001. 
1011010. 
1011011. 
101110. . 



1011110. 
1011111. 
1100000. 
1100001. 
1100010. 
1100011. 
1100100. 
1100101. 
1100110. 
1100111. 



1101000. 
1101001. 
1101010. 
1101011. 
1101100. 
1101101. 
1101110. 



byte 0 



byte 1 



byte 2 



b7 


b6 


b5 


b4 


b3 


b2 


b1 


bO 




jump%flag 0|1 #ref 


%flag 


TRUE 


#ref 


equal, not 


NOT 




and 


NOT 


or 


NOT 


xor 


NOT 


add, sub 


sub 


addc, subb 


sub 


Ish 


right 


ash 


right 


rote 


right 


rot 


right 


byteO 


byte 1 byte 2 


b7 


b6 


b5 


b4 


b3 


b2 


b1 


bO 




add8, sub8 


sub 


add8c, sub8b 


sub 


Ish8 


right 


ash8 


right 


rot8c 


right 


rot8 


right 


cast 


sign 


A,B 


byteO 


byte 1 byte 2 


b7 


b6 


b5 


b4 


b3 


b2 


b1 


bO 




equals, nots 


NOT 


ands 


NOT 


ors 


NOT 


xors 


NOT 


adds, subs 


sub 


addes, subbs 


sub 


Ishls, Ishrs 


right 


ashls, ashrs 


right 


rotcls, rotcrs 


right 


rotls, rotrs 


right 


byteO 


byte 1 byte 2 


b7 


b6 


b5 


b4 


b3 


b2 


b1 


bO 




add8s, sub8s 


sub 


add8cs, sub8bs 


sub 


Ish8ls, Ish8rs 


right 


ash8ls, ash8rs 


right 


rot8cls, rot8crs 


right 


rot8ls, rot8rs 


right 


casts 


sign 



Version " 

byte 3 



byte 3 



byte 3 



byte 3 



Version "D" 



643 



OxDE 


11011110 


OxDF 


11011111 


OxEO 


11100000 


OxEl 


11100001 


0xE2 


11100010 


0xE3 


11100011 


0xE4 


1110010. 


0xE6 


1110011. 


0xE8 


1110100. 


OxEA 


1110101. 


OxEC 


mono. 


OxEE 


1110111. 


OxFO 


11110000 


OxFl 


11110001 



byte 0 


byte 1 byte 2 


byte 3 


b7 b6 b5 b4 b3 b2 b1 


bO 






call 


#ref 


return 






int 


int 




iret 






imrl 


mask 




ivtl 


#ref 


flag_iO|1 


set 




flag_c 0|1 


set 






in n % 


A, B 


port 




in n (%) 


(I.J) 


port 


out % n 


A, B 


port 


out (%) n 


(I, J) 


port 


if_ackjump 


port 


#ref 


if ack call 


port 


#ref 



byteO 



0xF2 


1111001. 


0xF4 


1111010. 


0xF6 


1111011. 


0xF8 


1111100. 


Ox FA 


1111101. 


OxFC 


1111110. 


OxFE 


11111110 


OxFF 


11111111 



byte 1 



byte 2 



b7 b6 b5 b4 b3 b2 b1 


bO 




cmpr, testr 


test 


cmpi, testi 


test 


cmps, tests 


test 


cmp8i, test8i 


test 


cmp8s, test8s 


test 


call (%) 


I, J 


jump 


#ref | 


stop 





byte 3 



Table 11.41. Macrocode syntax. 



Macrocode syntax 


Description 


nop 


Not operate. 


cp %src , %dst 


Copy the src register content inside the dst 
register. Allowed registers are: I, J,A, B, 
BP, SP, C, FL. 


cp nl6 , %dst 


Assign a 16-bit constant to a register. Al- 
lowed destination registers are: I,J,A,B. 


cp (%l|%J), %A|%B 


Assign to register A or B the 16-bit value 
contained in memory at the address al- 
ready available from register I or J. 


cp %A | %B, (%I | %J) 


Copy in memory the 16-bit value of regis- 
ter A or B, to the location represented by 
the register / or /. 


cp nl6, (%I | %J) 


Assign in memory the 16-bit constant, to 
the location represented by the register / 
or J. 



644 



Version "D" 



Macrocode syntax 


Description 




Copy the 16-bit memory content at the 


cp (%I) 


cIUUICjj ICJJICdCllLCLl Uj ICglMCl 1 , LU L11C 

memory location represented oy me reg- 
ister J. 




Copy the 16-bit memory content at the 


cp (%J) 


aaaress represented oy register j , to tne 
memory location represented by the reg- 
ister /. 


cp8 n8 , %dst 


Assign a 8-bit constant to a register. Al- 
lowed destination registers are: I,J,A,B. 




Assign to register A or B the 8-bit value 


cp8 (%l|%J), %A|%B 


contained in memory at the address al- 
ready available from register I or J. 


cp8 %A | %B, (%I | %J) 


Conv in memorv the 8-bit value of register 
A or 5, to the location represented by the 
register I or J. 


CD 8 «5, (%I 1 %J) 


A cci cr n i n m pm rvr\7 tnp >\_ ni t crwi c1~iin1~ tn 
.rYaMgll 111 lllClllUlj L11C O UH CUlldLcillL, l\J 

tne location represented oy tne register i 
or J. 




Copy the 8-bit memory content at the 


cp8 (%I) 


'.\ H H tv*o c ranrpc p»n t^H r\\7 t^cti ct^T* T tn t n 
cIUUICjj ICpiC^CllLCU- Uj ICglMCl 1 , LU L11C 

memory location represented oy tne reg- 
ister J. 




Copy the 8-bit memory content at the ad- 


cp8 (%J) 


dress represented oy register j , to tne 
iiieiiiuiy lucdiiuii icpicsciiLcd vy uie icg- 
ister /. 


push reg 


Push at the top of the stack the 16-bit value 


contained inside the register. 


pop reg 


Pop from the stack a 16-bit value that is 


then assigned to the register. 


push8 reg 


Push at the top of the stack the 8-bit value 


contained inside the register. 


pop 8 reg 


Pop from the stack a 8 -bit value that is then 


assigned to the register. 



Version "D" 



645 



Macrocode syntax 


Description 


push nl6 


Push at the top of the stack the 16-bit con- 
stant. 


push n8 


Push at the top of the stack the 8-bit con- 
stant. 


push (%I | %J) 


Push at the ton of the stack the 1 6-bit value 
contained in memory, at the location rep- 
resented by register I or J. 


push (%I | %J) 


Push at the ton of the stack the 1 6-bit value 
contained in memory, at the location rep- 
resented by register I or J. 


push8 (%l|%J) 


Push at the ton of the stack the 8-bit value 

A V-*» LI 1 1 t~ I V L11V IV l_y V ' 1 lllv L.J 111V \~J L / 1 V V tl 1 LI ^/ 

contained in memory, at the location rep- 
resented by register I or J. 


pop (%I | %J) 


Pod from the ton of the stack a 1 6-bit that 

A 1 X 1X1 lllv IV V~J X lllv U tU-VXV 1.1 1_ V/ L/ll- 111 IX V 

is then copied at the memory location rep- 
resented by register I or J. 


pop8 (%l|%J) 


Pod from the ton of the stack a 8-bit that is 

A l_» 1 X 1X1 111V IV V~J VX lllv JIUV1V IX 1 V llllll 1U 

then copied at the memory location repre- 
sented by register I or J. 


jump #ref 


Jump to the address specified. 


jump %carry | %borrow^ 

| %zero | %negative^ 
| ^overflow, ^ 
^ 0|l, #ref 


Conditional jump. The first argument is 
a pseudo-register that selects the flag; the 
second argument means the value that the 
flag should have; the third argument is the 
address where the jump should go if the 
condition is met. 


equal 


C =A, updating the flags status 


not 


C = ~A, updating the flags status (one's 
complement). 


and 


C =A & B, updating the flags. 


nand 


C = ~(A & B), updating the flags. 



646 



Version "D" 



Macrocode syntax 


Description 


or 


C = A 1 B, updating the flags. 


nor 


C = ~(A 1 B), updating the flags. 


xor 


C = A A B, updating the flags. 


nxor 


C = ~(A A B), updating the flags. 


add 


C =A + B, updating the flags, 16-bit. 


sub 


C =A - B, updating the flags, 16-bit. 


addc 


C = A + B + carry, updating the flags, 16- 
bit. 


subb 


C = A - B - borrow, updating the flags, 
16-bit. 


lshl 


C = lshl(A), updating the flags: logic shift 
left, 16-bit. 


lshr 


C = lshr(A), updating the flags: logic shift 
right, 16-bit. 


ashl 


C = ashl(A), updating the flags: arithmetic 
shift left, 16-bit. 


ashr 


C = ashr(A), updating the flags: arithmetic 
shift right, 16-bit. 


rot cl 


C = rotcl(A), updating the flags: rotation 
left whith carry, 16-bit. 


rot cr 


C = rotcr(A), updating the flags: rotation 
right whith carry, 16-bit. 


rot 1 


C = rotl(A), updating the flags: rotation 
left, 16-bit. 


rot r 


C = rotr(A), updating the flags: rotation 
right, 16-bit. 



Version "D" 



647 



Macrocode syntax 


Description 


add8 


C =A + B, updating the flags, 8-bit. 


sub8 


C =A - B, updating the flags, 8-bit. 


add8c 


C = A + B + carry, updating the flags, 8- 
bit. 


sub8b 


C = A - B - borrow, updating the flags, 
8-bit. 


lsh81 


C = lsh81(A), updating the flags: logic 
shift left, 8-bit. 


lsh8r 


C = lsh8r(A), updating the flags: logic 
shift right, 8-bit. 


ash81 


C = ash81(A), updating the flags: arith- 
metic shift left, 8 -bit. 


ash8r 


C = ash8r(A), updating the flags: arith- 
metic shift right, 8-bit. 


rot 8cl 


C = rot8cl(A), updating the flags: rotation 
left whith carry, 8-bit. 


rot 8cr 


C = rot8cr(A), updating the flags: rotation 
right whith carry, 8 -bit. 


rot81 


C = rot81(A), updating the flags: rotation 
left, 8-bit. 


rot 8r 


C = rot8r(A), updating the flags: rotation 
right, 8 -bit. 


cast 0 | 1 %A | %B 


Adapt the register value to 8-bit, unsigned 
or signed, depending on the first argument. 


equals 


Read the 16-bit value on top of the stack 
and update the flags. 


not s 


Read the 16-bit value on top of the stack 
and replace it with the one's complement, 
updating the flags. 



648 



Version "D" 



Macrocode syntax 



Description 



ands 



Pop two 16-bit values from the top of the 
stack and push the bitwise AND of them, 
updating the flags, the registers A and B 
are overwritten. 



nands 



Pop two 16-bit values from the top of the 
stack and push the bitwise NAND of them, 
updating the flags, the registers A and B 
are overwritten. 



ors 



nors 



Pop two 16-bit values from the top of the 
stack and push the bitwise OR of them, up- 
dating the flags, the registers A and B are 
overwritten. 

Pop two 16-bit values from the top of the 
stack and push the bitwise NOR of them, 
updating the flags, the registers A and B 
are overwritten. 



xor s 



Pop two 16-bit values from the top of the 
stack and push the bitwise XOR of them, 
updating the flags, the registers A and B 
are overwritten. 



nxors 



Pop two 16-bit values from the top of the 
stack and push the bitwise NXOR of them, 
updating the flags, the registers A and B 
are overwritten. 



adds 



Pop two 16-bit values from the top of the 
stack and push the sum of them, updating 
the flags. To do the calculation, the regis- 
ters A and B are overwritten. 



subs 



addcs 



Pop a 16-bit values from the top of the 
stack and put it inside the register B ; then 
pop another 16-bit value and put inside 
the register A; then calculate A-B updat- 
ing the flags and push the result inside the 
stack again. 

Pop two 16-bit values from the top of the 
stack and push the sum with carry of them, 
updating the flags. To do the calculation, 
the registers A and B are overwritten. 



Version "D" 



649 



Macrocode syntax 



Description 



subbs 



Pop a 16-bit values from the top of the 
stack and put it inside the register B ; then 
pop another 16-bit value and put inside the 
register A; then calculate A -B -borrow 
updating the flags and push the result in- 
side the stack again. 



lshls 



lshrs 



ashls 



Pop a 16-bit values from the top of the 
stack and push the logic shift left of it, up- 
dating the flags. 

Pop a 16-bit values from the top of the 
stack and push the logic shift right of it, 
updating the flags. 

Pop a 16-bit values from the top of the 
stack and push the arithmetic shift left of 
it, updating the flags. 



ashrs 



Pop a 16-bit values from the top of the 
stack and push the arithmetic shift right of 
it, updating the flags. 



rot els 



Pop a 16-bit values from the top of the 
stack and push the rotation left with carry 
of it, updating the flags. 



rotors 



Pop a 16-bit values from the top of the 
stack and push the rotation right with carry 
of it, updating the flags. 



rot Is 



Pop a 16-bit values from the top of the 
stack and push the rotation left of it, up- 
dating the flags. 



rot rs 



Pop a 16-bit values from the top of the 
stack and push the rotation right of it, up- 
dating the flags. 



add8s 



Pop two 8-bit values from the top of the 
stack and push the sum of them, updating 
the flags. To do the calculation, the regis- 
ters A and B are overwritten. 



650 



Version "D" 



Macrocode syntax 



Description 



sub8s 



Pop a 8-bit values from the top of the stack 
and put it inside the register B ; then pop 
another 16-bit value and put inside the reg- 
ister A; then calculate A -B updating the 
flags and push the result inside the stack 
again. 



add8cs 



sub8bs 



Pop two 8-bit values from the top of the 
stack and push the sum with carry of them, 
updating the flags. To do the calculation, 
the registers A and B are overwritten. 
Pop a 8-bit values from the top of the stack 
and put it inside the register B ; then pop 
another 16-bit value and put inside the reg- 
ister A; then calculate A -B -borrow up- 
dating the flags and push the result inside 
the stack again. 



Ish81s 



Pop a 8-bit values from the top of the stack 
and push the logic shift left of it, updating 
the flags. 



Ish8rs 



Pop a 8-bit values from the top of the stack 
and push the logic shift right of it, updating 
the flags. 



ash81s 



Pop a 8-bit values from the top of the stack 
and push the arithmetic shift left of it, up- 
dating the flags. 



ash8r s 



rotc81s 



rot c8rs 



Pop a 8-bit values from the top of the stack 
and push the arithmetic shift right of it, up- 
dating the flags. 

Pop a 8-bit values from the top of the stack 
and push the rotation left with carry of it, 
updating the flags. 

Pop a 8-bit values from the top of the stack 
and push the rotation right with carry of it, 
updating the flags. 



rot 81s 



Pop a 8-bit values from the top of the stack 
and push the rotation left of it, updating the 
flags. 



Version "D" 



651 



Macrocode syntax 


Description 


rot 8r s 


Pod a 8-bit values from the ton of the stack 
and push the rotation right of it, updating 
the flags. 


casts 0 | 1 


Pop a 16-bit value from the top of the stack 
and Dush the same value adanted to 8-bit 
unsigned or signed, depending on the ar- 
gument. 


call #ref 


Call the nrocedure that starts at the arsu- 

V/Ull U1V l_/A V-'V-' V*- VIA V- - lllLil JIU1 I J III l>llv HI V* 

ment reference: the registers FL and PC 
are pushed inside the stack. 


call (%I|%J) 


Call the procedure that starts at the posi- 
tion contamea msiae register 1 or j . tne 
registers FL and PC are pushed inside the 
stack. 


return 


Return from a previous call: the registers 
PC and FL are retrieved from the stack. 


int n8 


Software interrupt call: the registers FL 
and PC are pushed inside the stack. 


iret 


Return from an interrupt: the registers PC 
and FL are retrieved from the stack. 


imrl n8 


Load the IMR: interrupt mask register. 


ivtl #ref 


Load the TVT' interrunt vector table The 

-1 — J V' U1V AT A • AAA Wvl A VI Y-S X, V V-* V IV' 1 ILiUlV • A 11V 

argument is the interrupt vector table start 
address in memory. 


f lag_i 0 | 1 


Reset or set the flag that allow the hard- 
ware interrupts. 


f lag_c 0 | 1 


Reset or set the carry (borrow) flag. 


in n8, %A | %B 


Read from the I/O address specified, a byte 
that is copied inside register A or B. 


in n8, (%I | %J) 


Read from the I/O address specified, a byte 
that is copied in memory, at the address 
specified by register I or J. 



652 



Version "D" 



Macrocode syntax 



Description 



out %A|%B, n8 



Write to the I/O address specified, a byte 
that is read from register A or B . 



out (%I I %J) , n8 



Write to the I/O address specified, a byte 
that is read from memory, at the address 
specified by register I or J. 



ifack_jump n8 , #ref 



ifack_call n8 , #ref 



If the I/O port gives an acknoledge report, 
then jump to the specified address. 

If the I/O port gives an acknoledge report, 
then call the specified procedure. 



cmpr 



Calculate A -B, updating the flags, with- 
out modifying the accumulator. 



testr 



Calculate A&B (bitwise AND), updating 
the flags, without modifying the accumu- 
lator. 



cmpi 



Load A with the value contained in mem- 
ory at the address represented by the reg- 
ister /; load B with the value contained in 
memory at the address represented by the 
register J; then calculate A -B, updating 
the flags, without modifying the accumu- 
lator. 



test i 



cmps 



Load A with the value contained in mem- 
ory at the address represented by the reg- 
ister /; load B with the value contained in 
memory at the address represented by the 
register J; then calculate A&B (bitwise 
AND), updating the flags, without modi- 
fying the accumulator. 
Read from the top of the stack a 16-bit 
value and put it inside the register B ; read 
from the stack, just under the previous 
value, a 16-bit value and put it inside the 
register A; then calculate A -B, updating 
the flags, without modifying the accumu- 
lator. 



Version "D" 



653 



Macrocode syntax 



Description 



tests 



Read from the top of the stack a 16-bit 
value and put it inside the register B ; read 
from the stack, just under the previous 
value, a 16-bit value and put it inside the 
register A; then calculate A&B, updating 
the flags, without modifying the accumu- 
lator. 



cmp8r 



Calculate 8-bit A -B, updating the flags, 
without modifying the accumulator. 



test 8r 



Calculate 8-bit A&B (bitwise AND), up- 
dating the flags, without modifying the ac- 
cumulator. 



cmp8i 



Load 8 -bit inside A with the value con- 
tained in memory at the address repre- 
sented by the register /; load 8-bit inside B 
with the value contained in memory at the 
address represented by the register J; then 
calculate A -B, updating the flags, without 
modifying the accumulator. 



test 8i 



Load 8 -bit inside A with the value con- 
tained in memory at the address repre- 
sented by the register /; load 8-bit inside B 
with the value contained in memory at the 
address represented by the register J; then 
calculate A&B, updating the flags, with- 
out modifying the accumulator. 



cmp8s 



Read from the top of the stack a 8 -bit value 
and put it inside the register B ; read from 
the stack, just under the previous value, a 
8 -bit value and put it inside the register 
A ; then calculate A -B, updating the flags, 
without modifying the accumulator. 



654 



Version "D" 



Macrocode syntax 


Description 


test 8s 


Read from the top of the stack a 8 -bit value 
and put it inside the register B ; read from 
the stack, just under the previous value, a 
8-bit value and nut it inside the register 

V_J C 1 V T HI Li V Lillvi L/ Vit X V 111 J1V1V H1W IV-'&.lUW-'l 

A ; then calculate A &B , updating the flags, 
without modifying the accumulator. 


stop 


Stop the system. 



Listing 11.42. Registers, flags and opcodes encoded for TKGate. 

registers 1=0, J=l, A=2, B=3, BP=4, SP=5, C=6, FL=7; 



registers carry= 

// 

op nop { 

map nop : 

operands { - = 

}; 
// 

op cp { 

// 

map nop : 
map cp_i_j 
map cp_i_a 
map cp_i_b 
map cp_i_bp : 
map cp_i_sp: 
map cp_i_c : 
map cp_i_f 1 : 
map cp_ j_i : 
map nop : 
map cp_ j_a : 
map cp_ j_b : 
map cp_ j_bp : 
map cp_j_sp: 
map cp_ j_c : 
map cp_j_fl: 
map cp_a_i : 



=0, borrow=0, zero=l, negative=2, overflow=3; 



0x00; // not operate 

{ +0=0x00; }; }; 



0x00 
0x01 
0x02 
0x03 
0x04 
0x05 
0x06 
0x07 
0x08 
0x09 
OxOA 
OxOB 
OxOC 
OxOD 
OxOE 
OxOF 
0x10 



00 

// 00000000 
// 00000001 
// 00000010 
// 00000011 
// 00000100 
// 00000101 
// 00000110 
// 00000111 
// 00001000 
// 00001001 
// 00001010 
// 00001011 
// 00001100 
// 00001101 
// 00001110 
// 00001111 
// 00010000 



cp %, % 

cp %I, %J 

cp %I, %J 

cp %I, %A 

cp %I, %B 

cp %I, %BP 

cp %I, %SP 

cp %I, %C 

cp %I, %FL 

cp %J, %I 

cp %J, %J 

cp %J, %A 

cp %J, %B 

cp %J, %BP 

cp %J, %SP 

cp %J, %C 

cp %J, %FL 

cp %A, %I 



= nop 



= nop 



Version "D" 



655 



map 


cp_a_j : 


0x11; 


// 


00010001 




cp 


%A, %J 




map 


nop : 


0x12; 


// 


00010010 




cp 


%A, %A = 


nop 


map 


cp_a_b : 


0x13; 


// 


00010011 




cp 


%A, %B 




map 


cp_a_bp : 


0x14; 


// 


00010100 


— 


cp 


%A, %BP 




map 


cp_a_sp : 


0x15; 


// 


00010101 


= 


cp 


%A, %SP 




map 


cp_a_c : 


0x16; 


// 


00010110 


— 


cp 


%A, %C 




map 


cp_a_f 1 : 


0x17; 


// 


00010111 


— 


cp 


%A, %FL 




map 


cp_b_i : 


0x18; 


// 


00011000 


— 


cp 


%B, %I 




map 


cp_b_j : 


0x19; 


// 


00011001 


— 


cp 


%B, %J 




map 


cp_b_a : 


OxlA; 


// 


00011010 


— 


cp 


%B, %A 




map 


nop : 


OxlB; 


// 


00011011 


= 


cp 


%B, %B = 


nop 


map 


cp_b_bp : 


OxlC; 


// 


00011100 




cp 


%B, %BP 




map 


cp_b_sp : 


OxlD; 


// 


00011101 


= 


cp 


%B, %SP 




map 


cp_b_c : 


OxlE; 


// 


00011110 


— 


cp 


%B, %C 




map 


cp_b_f 1 : 


OxlF; 


// 


00011111 


— 


cp 


%B, %FL 




map 


cp_bp_i : 


0x20; 


// 


00100000 


= 


cp 


%BP, %I 




map 


cp_bp_ j : 


0x21; 


// 


00100001 


= 


cp 


%BP, %J 




map 


cp_bp_a : 


0x22; 


// 


00100010 


— 


cp 


%BP, %A 




map 


cp_bp_b : 


0x23; 


// 


00100011 


— 


cp 


%BP, %B 




map 


nop : 


0x2 4; 


// 


00100100 


— 


cp 


%BP, %BP 


= nop 


map 


cp_bp_sp : 


0x2 5; 


// 


00100101 


— 


cp 


%BP, %SP 




map 


cp_bp_c : 


0x26; 


// 


00100110 


= 


cp 


%BP, %C 


= nop 


map 


cp_bp_f 1 : 


0x2 7; 


// 


00100111 


— 


cp 


%BP, %FL 




map 


cp_sp_i : 


0x28; 


// 


00101000 


— 


cp 


%SP, %I 




map 


cp_sp_ j : 


0x29; 


// 


00101001 


— 


cp 


%SP, %J 




map 


cp_sp_a : 


0x2A; 


// 


00101010 


— 


cp 


%SP, %A 




map 


cp_sp_b : 


0x2B; 


// 


00101011 


— 


cp 


%SP, %B 




map 


cp_sp_bp : 


0x2C; 


// 


00101100 


= 


cp 


%SP, %BP 




map 


nop : 


0x2D; 


// 


00101101 


— 


cp 


%SP, %SP 


= nop 


map 


cp_sp_c : 


0x2E; 


// 


00101110 


= 


cp 


%SP, %C 




map 


cp_sp_f 1 : 


0x2F; 


// 


00101111 


= 


cp 


%SP, %FL 




map 


cp_c_i : 


0x30; 


// 


00110000 


— 


cp 


%C, %I 




map 


cp_c_j : 


0x31; 


// 


00110001 


= 


cp 


%C, %J 




map 


cp_c_a : 


0x32; 


// 


00110010 


— 


cp 


%C, %A 




map 


cp_c_b : 


0x33; 


// 


00110011 


= 


cp 


%C, %B 




map 


cp_c_bp : 


0x34; 


// 


00110100 


— 


cp 


%C, %BP 




map 


cp_c_sp : 


0x35; 


// 


00110101 


— 


cp 


%C, %SP 




map 


nop : 


0x36; 


// 


00110110 




cp 


%C, %C 


= nop 


map 


cp_c_f 1 : 


0x37; 


// 


00110111 




cp 


%C, %FL 




map 


cp_f l_i : 


0x38; 


// 


00111000 




cp 


%FL, %I 





656 



Version "D" 



map 


cp_f l_j : 


0x39; 


// 


00111001 




cp 


%FL, %J 






map 


cp_f l_a : 


0x3A; 


// 


00111010 




cp 


%FL, %A 






map 


cp_f l_b : 


0x3B; 


// 


00111011 




cp 


%FL, %B 






map 


cp_f l_bp : 


0x3C; 


// 


00111100 


= 


cp 


%FL, %BP 






map 


cp_f l_sp : 


0x3D; 


// 


00111101 


— 


cp 


%FL, %SP 






map 


cp_f l_c : 


0x3E; 


// 


00111110 


— 


cp 


%FL, %C 






map 


nop : 


0x3F; 


// 


00111111 


= 


cp 


%FL, %FL = 


nop 




// 








010000. . 


— 


cp 


#,% 






map 


cp_num_i : 


0x40; 


// 


01000000 




cp 


#, %I 






map 


cp_num_j : 


0x41; 


// 


01000001 


= 


cp 


#, %J 






map 


cp_num_a : 


0x42; 


// 


01000010 


= 


cp 


#, %A 






map 


cp_num_b : 


0x43; 


// 


01000011 




cp 


#, %B 






// 








010001. . 


= 


cp 


(%),% 






map 


cp_mi_a : 


0x44; 


// 


01000100 




cp 


(%I) , %A 






map 


cp_mi_b : 


0x45; 


// 


01000101 


— 


cp 


(%I) , %B 






map 


cp_m j_a : 


0x46; 


// 


01000110 


= 


cp 


(%J) , %A 






map 


cp_m j_b : 


0x47; 


// 


01000111 


= 


cp 


(%J) , %B 






// 








010010. . 


= 


cp 


%, %I 






map 


cp_a_mi : 


0x48; 


// 


01001000 


— 


cp 


%A, (%I) 






map 


cp_a_m j : 


0x49; 


// 


01001001 


— 


cp 


%A, (%J) 






map 


cp_b_mi : 


0x4A; 


// 


01001010 


— 


cp 


%B, (%I) 






map 


cp_b_m j : 


0x4B; 


// 


01001011 


— 


cp 


%B, (%J) 






// 








0100110. 


— 


cp 


#, (%) 






map 


cp_num_mi 


: 0x4C; 


// 


01001100 


= 


cp 


#, 






map 


cp_num_m j 


: 0x4D; 


// 


01001101 


— 


cp 


#, (%J) 






// 








0100111 . 


— 


cp 


(%) 






map 


cp_mi_mj : 


0x4E; 


// 


01001110 




cp 


(%D 






map 


cp_m j_mi : 


0x4F; 


// 


01001111 




cp 


(%J) 






// 




















operands { 


















%1,%2 = { 


+0=0x00; 


+ 0 [5:3]=%1; 


+ 0 [2 : 


0]=%2; }; 






#1,%2 = { 


+0=0x40; 


+0 [1 : 0] =%2; 


+1 


=#1[7:0]; +2= 


#1 [15: 


8]; }; 


(% 


1) ,%2 = { 


+0=0x44; 


+0 [1 : 1] =%1; 


+ 0 [0 : 


0]=%2; }; 






%1, (%2) = { 


+0=0x48; 


+0 [1 : 1] =%1; 


+ 0 [0 : 


0]=%2; }; 






#1, (%2) = { 


+0=0x4C; 


+0 [0 : 0] =%2; 


+1 


=#1[7:0]; +2= 


#1 [15: 


8]; }; 


(% 

}; 


1) = { 


+0=0x4E; 


+0 [0 : 0] =%1; 


}; 










}; 

op cp8 { 


















// 








010100. . 




cp8 #,% 







Version "D" 



657 



map 


cp8 


_num_i : 


0x50; 


// 


01010000 


= cp8 


#, %I 


map 


cp8 


_num_ j : 


0x51; 


// 


01010001 


= cp8 


#, %J 


map 


cp8 


_num_a : 


0x52; 


// 


01010010 


= cp8 


#, %A 


map 


cp8 


_num_b : 


0x53; 


// 


01010011 


= cp8 


#, %B 


// 










010101. . 


= cp8 


(%),% 


map 


cp8 


_mi_a : 


0x54; 


// 


01010100 


= cp8 


(%I) , %A 


map 


cp8 


_mi_b : 


0x55; 


// 


01010101 


= cp8 


(%I) , %B 


map 


cp8 


_m j_a : 


0x5 6; 


// 


01010110 


= cp8 


(%J) , %A 


map 


cp8 


_m j_b : 


0x57; 


// 


01010111 


= cp8 


(%J) , %B 


// 










010110. . 


= cp8 


%, (%) 


map 


cp8 


_a_mi : 


0x58; 


// 


01011000 


= cp8 


%A, (%I) 


map 


cp8 


_a_mj : 


0x59; 


// 


01011001 


= cp8 


%A, (%J) 


map 


cp8 


_b_mi : 


0x5A; 


// 


01011010 


= cp8 


%B, (%I) 


map 


cp8 


_b_mj : 


0x5B; 


// 


01011011 


= cp8 


%B, (%J) 


// 










0101110. 


= cp8 


#, (%) 


map 


cp8 


_num_mi 


: 0x5C; 


// 


01011100 


= cp8 


#, (%D 


map 


cp8 


_num_m j 


: 0x5D; 


// 


01011101 


= cp8 


#, (%J) 


// 










0101111 . 


= cp8 


(%) 


map 


cp8 


_mi_m j : 


0x5E; 


// 


01011110 


= cp8 


(%I) 


map 


cp8 


_m j_mi : 


0x5F; 


// 


01011111 


= cp8 


(%J) 


// 
















operands { 












#1,%2 


= { 


+0=0x50; 


+ 0 


[1 : 0] =%2; 


+ 1=#1 


[7:0]; }; 


(• 


*D , 


%2 = { 


+0=0x54; 


+ 0 


[1 : 1] =%1; 


+ 0 [0 : 


0]=%2; }; 


%1, (% 


2) = { 


+0=0x58; 


+ 0 


[1 : 1] =%1; 


+ 0 [0 : 


0]=%2; }; 


#1, (% 


2) = { 


+0=0x5C; 


+ 0 


[0 : 0] =%2; 


+ 1=#1 


[7:0]; }; 


(• 

}; 


*D 


= { 


+0=0x5E; 


+ 0 


[0 : 0] =%1; 


}; 




}; 
// 
















op push { 














// 










01100. . . 


= push 


% 


map 


push_i : 


0x60; 


// 


01100000 


= push 


%I 


map 


push_j : 


0x61; 


// 


01100001 


= push 


%J 


map 


push_a : 


0x62; 


// 


01100010 


= push 


%A 


map 


push_b : 


0x63; 


// 


01100011 


= push 


%B 


map 


push_bp : 


0x64; 


// 


01100100 


= push 


%BP 


map 


push_sp : 


0x65; 


// 


01100101 


= push 


%SP 


map 


push_c : 


0x66; 


// 


01100110 


= push 


%C 


map 


push_f 1 : 


0x67; 


// 


01100111 


= push 


%FL 



658 



Version "D" 



// 
















map 


push 


_num : 


0x80; 


// 


10000000 


— 


push # 


// 
















map 


push 


_mi : 


0x82; 


// 


10000010 




push (%I) 


map 


push 


_mj : 


0x83; 


// 


10000011 


— 


push (%J) 


// 
















operands 


{ 












%1 




{ +o 


=0x60; +0 


[2 : 0 


]=%i; }; 






#1 




{ +o 


=0x80; +1 = 


= #1 [ 


7:0]; +2= 


#1 


[15:8]; }; 


(* 

}; 


1) = 


{ +o 


=0x82; +0 


[0:0 


]=%i; }; 






}; 

op pop { 














// 










OHIO. . . 


— 


pop % 


map 


pop_ 


i : 


0x70; 


// 


01110000 


— 


pop %I 


map 


pop_ 


j = 


0x71; 


// 


01110001 


— 


pop %J 


map 


pop_ 


a : 


0x72; 


// 


01110010 


= 


pop %A 


map 


pop_ 


b: 


0x7 3; 


// 


01110011 


— 


pop %B 


map 


pop_ 


op : 


0x7 4; 


// 


01110100 


= 


pop %BP 


map 


pop_ 


sp : 


0x7 5; 


// 


01110101 


— 


pop %SP 


map 


pop_ 


c : 


0x7 6; 


// 


01110110 


— 


pop %C 


map 


pop_ 


fl : 


0x7 7; 


// 


01110111 


= 


pop %FL 


// 










1000011. 


= 


pop (%) 


map 


pop_ 


mi : 


0x86; 


// 


10000110 


— 


pop (%I) 


map 


pop_ 


mj : 


0x87; 


// 


10000111 




pop (%J) 


// 
















operands 


{ 












%1 




{ +o 


=0x70; +0[2:0 


]=%i; }; 






(* 

}; 


1) = 


{ +o 


=0x86; +0 


[0:0 


]=%i; }; 






}; 
// 
















op push8 { 














// 










01101. . . 


— 


push8 % 


map 


push 


8_i: 


0x68; 


// 


01101000 


— 


push8 %I 


map 


push 


8_j: 


0x69; 


// 


01101001 


— 


push8 %J 


map 


push 


8_a: 


0x6A; 


// 


01101010 


= 


push8 %A 


map 


push 


8_b: 


0x6B; 


// 


01101011 




push8 %B 


map 


push 


8_bp: 


0x6C; 


// 


01101100 




push 8 %BP 


map 


push 


8_sp : 


0x6D; 


// 


01101101 




push8 %SP 



Version "D" 



659 



map 


push? 


3_c: 


0x6E; 


// 


01101110 


— 


push 8 


%C 


map 


push? 


3_fl : 


0x6F; 


// 


01101111 


— 


push 8 


%FL 


// 


















map 


push? 


3_num : 


0x81; 


// 


10000001 


— 


push 8 


# 


// 










1000010. 


— 


push 8 


(%I) 


map 


push? 


3_mi : 


0x84; 


// 


10000100 


— 


push 8 


(%I) 


map 


push? 


3_mj : 


0x85; 


// 


10000101 


— 


push 8 


(%J) 


// 


















operands 


{ 














%1 




{ +o= 


0x68; +0 


[2: 0 


]=%i; }; 








#1 




{ +0 = 


0x81; +1 


'J : 0 


]=#i; }; 








(%D = 

}; 


{ +0 = 


0x81; +0 


;o : 0 


]=%i; }; 








}; 

op pop 


8 { 
















// 










01111 . . . 


— 


pop8 


% 


map 


pop8_ 


_i : 


0x78; 


// 


01111000 


— 


pop8 


%I 


map 


pop8_ 


_j : 


0x7 9; 


// 


01111001 


— 


pop8 


%J 


map 


pop8_ 


_a : 


0x7A; 


// 


01111010 


— 


pop8 


%A 


map 


pop8_ 


_b: 


0x7B; 


// 


01111011 


— 


pop8 


%B 


map 


pop8_ 


_bp : 


0x7C; 


// 


01111100 


— 


pop8 


%BP 


map 


pop8_ 


_sp : 


0x7D; 


// 


01111101 


— 


pop8 


%SP 


map 


pop8_ 


_c : 


0x7E; 


// 


01111110 


— 


pop8 


%C 


map 


pop8_ 


_f 1 : 


0x7F; 


// 


01111111 




pop8 


%FL 


// 








// 


1000100. 


— 


pop8 


(%) 


map 


pop8_ 


_mi : 


0x88; 


// 


10001000 


— 


pop8 


(%I) 


map 


pop8_ 


_mj : 


0x89; 


// 


10001001 


— 


pop8 


(%J) 


// 


















operands 


{ 














%1 




{ +0 = 


0x78; +0 


[2: 0 


]=%i; }; 








}; 


1) = 


{ +o= 


0x88; +0 


;o : 0 


]=%i; }; 








}; 
// 


















op jump { 
















map 


jump_ 


_nc : 


0x90; 


// 


10010000 


— 


jump 


%carry 0 # 


map 


jump_ 


_c : 


0x91; 


// 


10010001 


— 


jump 


% carry 1 # 


map 


jump_ 


_nz : 


0x92; 


// 


10010010 




jump 


%zero 0 # 


map 


jump_ 


_z : 


0x93; 


// 


10010011 




jump 


%zero 1 # 


map 


jump_ 


_nn : 


0x94; 


// 


10010100 




jump 


%negative 0 # 



660 



Version "D" 



map jump_n: 


0x95; // 10010101 = 


jump %negative 


1 


# 


map jump_no: 


0x96; // 10010110 = 


jump %overflow 


0 


# 


map jump_o: 


0x97; // 10010111 = 


jump %overflow 


1 


# 


// 










map jump: 


OxFE; // 11111110 = 


jump # 






// 










operands { 










%1, #2,#3 


= { +0=0x90; +0 [2 : 1] =%1; 


+ 0 [0:0]=#2; 








+1=#3[7:0]; +2=#3[15 


8]; }; 






#1 

}; 


= { +0 = 0xFE; +1 = #1 [7:0]; 


+2=#1[15:8]; }; 






}; 
// 










op equal { 










map equal: 


0x98; // 10011000 = 


equal 






operands { - 

}; 


= { +0=0x98; }; }; 








op not { 










map not : 


0x99; // 10011001 = 


not 






operands { - 


= { +0=0x99; }; }; 








}; 
// 










op and { 










map and: 


0x9A; // 10011010 = 


and 






operands { - 

}; 


= { +0=0x9A; }; }; 








op nand { 










map nand: 


0x9B; // 10011011 = 


nand 






operands { - 


= { +0=0x9B; }; }; 








}; 
// 










op or { 










map or : 


0x9C; // 10011100 = 


or 






operands { - 

}; 


= { +0=0x9C; }; }; 








op nor | 










map nor: 


0x9D; // 10011101 = 


nor 






operands { - 


= { +0=0x9D; }; }; 








}; 
// 











Version "D" 



661 



op xor { 












map xor: 




0x9E; // 


10011110 


= 


xor 


operands 

}; 


{ - 


- = { +0=0x9E; 


}; }; 






op nxor | 












map nxor 




0x9F; // 


10011111 


= 


nxor 


operands 


{ - 


- = { +0=0x9F; 


}; }; 






}; 
// 












op add { 












map add: 




OxAO; // 


10100000 


= 


add 


operands 


{ - 


- = { +0=0xA0; 


}; }; 






}; 

op sub { 












map sub: 




OxAl; // 


10100001 


= 


sub 


operands 


{ - 


- = { +0=0xAl; 


}; }; 






}; 
// 












op addc { 












map addc 




0xA2; // 


10100010 


= 


addc 


operands 

}; 


{ - 


- = { +0=0xA2; 


}; }; 






op subb { 












map subb 




0xA3; // 


10100011 


= 


subb 


operands 


{ - 


- = { +0=0xA3; 


}; }; 






}; 
// 












op lshl { 












map lshl 




0xA4; // 


10100100 


= 


lshl 


operands 

}; 


{ - 


- = { +0=0xA4; 


}; }; 






op lshr j 












map lshr 




0xA5; // 


10100101 


= 


lshr 


operands 


{ - 


- = { +0=0xA5; 


}; }; 






}; 
// 












op ashl { 












map ashl 




0xA6; // 


10100110 




ashl 


operands 

}; 


{ - 


- = { +0=0xA6; 


}; }; 







662 



Version "D" 



op ashr { 
map ashr: 
operands { - 


0xA7; // 
- = { +0=0xA7; 


10100111 

}; }; 




ashr 


}; 
// 

op rotcl { 
map rotcl: 
operands { - 

}; 


0xA8; // 
- = { +0=0xA8; 


10101000 

}; }; 




rotcl 


op rotcr { 
map rotcr: 
operands { - 


0xA9; // 
- = { +0=0xA9; 


10101001 

}; }; 




rotcr 


}; 
// 

op rotl { 
map rotl : 
operands { - 

}; 


OxAA; // 
- = { +0=0xAA; 


10101010 

}; }; 




rotl 


op rotr j 
map rotr: 
operands { - 


OxAB; // 
- = { +0=0xAB; 


10101011 

}; }; 




rotr 


}; 
// 

op add8 { 
map add8 : 
operands { - 


OxAC; // 
- = { +0=0xAC; 


10101100 

}; }; 




add8 


}; 

op sub8 { 
map sub8 : 
operands { - 


OxAD; // 
- = { +0=0xAD; 


10101101 

}; }; 




sub8 


}; 
// 

op add8c { 
map add8c: 
operands { - 

}; 


OxAE; // 
- = { +0=0xAE; 


10101110 

}; }; 




addc8 


op sub8b { 
map sub8b: 
operands { - 

}; 


OxAF; // 
- = { +0=0xAF; 


10101111 

}; }; 




subb8 



Version "D" 



663 



// 

op lsh81 { 
map lsh81: 
operands { - = 

}; 


OxBO; // 
{ +0=0xB0; 


10110000 

}; }; 




lshl81 


op lsh8r { 
map lsh8r: 
operands { - = 


OxBl; // 
{ +0=0xBl; 


10110001 

}; }; 




lshl8r 


}; 
// 

op ash81 { 
map ash81: 
operands { - = 

}; 


0xB2; // 
{ +0=0xB2; 


10110010 

}; }; 




ashl81 


op ash8r { 
map ash8r: 
operands { - = 


0xB3; // 
{ +0=0xB3; 


10110011 

}; }; 




ashl8r 


}; 
// 

op rot8cl { 
map rot 8cl : 
operands { - = 

}; 


0xB4; // 
{ +0=0xB4; 


10110100 

}; }; 




rotc81 


op rot8cr { 
map rot8cr: 
operands { - = 


0xB5; // 
{ +0=0xB5; 


10110101 

}; }; 




rotc8r 


}; 
// 

op rot81 { 
map rot 81: 
operands { - = 

}; 


0xB6; // 
{ +0=0xB6; 


10110110 

}; }; 




rot 81 


op rot8r { 
map rot8r: 
operands { - = 

}; 


0xB7; // 
{ +0=0xB7; 


10110111 

}; }; 




rot8r 


// 

op cast { 
// 

map cast_uns_a 


// 

: 0xB8; // 


101110. . 
10111000 




cast <sig>, % 
cast 0 , %A 



664 



Version "D" 



map cast_ 


_uns_ 


b 


: 0xB9; // 


10111001 


— 


cast 0, %B 




map cast_ 


_sig_ 


_a 


: OxBA; // 


10111010 




cast 1, %A 




map cast_ 


_sig_ 


b 


: OxBB; // 


10111011 




cast 1 , %B 




operands 


{ 














#1,%2 = 

}; 


{ + 0 


=0xB8; +0[1:1]=#1; +0[0: 


0]=%2; }; 




}; 
// 
















op equals { 
















map equals : 




OxBC; // 


10111100 




stack <= %A 




operands 

}; 


{ " 


= 


{ +0=0xBC; 


}; }; 








op nots { 
















map nots : 






OxBD; // 


10111101 


= 


stack <= NOT %A 


operands 


{ " 


= 


{ +0=0xBD; 


}; }; 








}; 
// 
















op ands { 
















map ands : 






OxBE; // 


10111110 


= 


stack <= %A 


AND %B 


operands 

}; 


{ " 




{ +0=0xBE; 


}; }; 








op nands { 
















map nands : 




OxBF; // 


10111111 


= 


stack <= %A 


NAND %B 


operands 


{ " 




{ +0=0xBF; 


}; }; 








}; 
// 
















op ors { 
















map ors: 






OxCO; // 


11000000 


= 


stack <= %A 


OR %B 


operands 

}; 


{ " 




{ +0=0xC0; 


}; }; 








op nors { 
















map nors : 






OxCl; // 


11000001 




stack <= %A 


NOR %B 


operands 


{ " 




{ +0=0xCl; 


}; }; 








}; 
// 
















op xors { 
















map xors : 






0xC2; // 


11000010 




stack <= %A 


XOR %B 


operands 

}; 


{ " 




{ +0=0xC2; 


}; }; 








op nxors { 

















Version "D" 



665 



map nxor s : 
operands { - 


- = { 


0xC3; // 
+0=0xC3; 


11000011 

}; }; 




stack 


<= 


%A NXOR 


%B 


}; 
// 

op adds { 
map adds : 
operands { - 

}; 


- = { 


0xC4; // 
+0=0xC4 ; 


11000100 

}; }; 




stack 


<= 


%A + 


%B 




op subs { 
map subs : 
operands { - 


- = { 


0xC5; // 
+0=0xC5; 


11000101 

}; }; 




stack 


<= 


%A ~ 


%B 




}; 
// 

op addcs { 
map addcs: 
operands { - 


- = { 


0xC6; // 
+0=0xC6; 


11000110 

}; }; 




stack 


<= 


%A + 


%B 


+ % carry 


}; 

op subbs { 
map subbs : 
operands { - 


- = { 


0xC7; // 
+0=0xC7; 


11000111 

}; }; 




stack 


<= 


%A ~ 


%B 


- % carry 


}; 
// 

op lshls { 
map lshls : 
operands { - 

}; 


- = { 


0xC8; // 
+0=0xC8; 


11001000 

}; }; 




stack 


<= 


lshl 






op lshrs j 
map lshrs : 
operands { - 


- = { 


0xC9; // 
+0=0xC9; 


11001001 

}; }; 




stack 


<= 


lshr 






}; 
// 

op ashls { 
map ashls : 
operands { - 

}; 


- = { 


OxCA; // 
+0=0xCA; 


11001010 

}; }; 




stack 


<= 


ashl 






op ashrs { 
map ashrs : 
operands { - 


- = { 


OxCB; // 
+0=0xCB; 


11001011 

}; }; 


= 


stack 


<= 


ashr 






}; 
// 





















666 



Version "D" 



op rotcls { 
map rotcls : 
operands { - 

}; 


- = { 


OxCC; // 
+0=0xCC; 


11001100 

}; }; 




stack <= rotcl 


op rotors { 
map rotors : 
operands { - 


- = { 


OxCD; // 
+0=0xCD; 


11001101 

}; }; 




stack <= rotcr 


}; 
// 

op rotls { 
map rotls : 
operands { - 

}; 


- = { 


OxCE; // 
+0=0xCE; 


11001110 

}; }; 




stack <= rotl 


op rotrs { 
map rotrs : 
operands { - 


- = { 


OxCF; // 
+0=0xCF; 


11001111 

}; }; 




stack <= rotr 


}; 
// 

op add8s { 
map add8s: 
operands { - 

}; 


- = { 


OxDO; // 
+0=0xD0; 


11010000 

}; }; 




stack8 <= + 


op sub 8s { 
map sub8s: 
operands { - 


- = { 


OxDl; // 
+0=0xDl; 


11010001 

}; }; 




stack 8 <= - 


}; 
// 

op add8cs { 
map add8cs: 
operands { - 

}; 


- = { 


0xD2; // 
+0=0xD2; 


11010010 

}; }; 




stack8 <= + + %carry 


op sub8bs { 
map sub8bs : 
operands { - 


- = { 


0xD3; // 
+0=0xD3; 


11010011 

}; }; 




stack8 <= - - %carry 


}; 
// 

op lsh81s { 
map lsh8 Is : 
operands { - 

}; 


- = { 


0xD4; // 
+0=0xD4; 


11010100 

}; }; 




stack8 <= lsh8r 



Version "D" 



667 



op lsh8rs { 
map lsh8rs : 
operands { - = 


0xD5; // 
{ +0=0xD5; 


11010101 

}; }; 




stack8 <= 


lsh8r 


}; 
// 

op ash81s { 
map ash8 Is : 
operands { - = 

}; 


0xD6; // 
{ +0=0xD6; 


11010110 

}; }; 




stack8 <= 


ash81 


op ash8rs { 
map ash8rs : 
operands { - = 


0xD7; // 
{ +0=0xD7; 


11010111 

}; }; 




stack8 <= 


ash8r 


}; 
// 

op rot8cls { 
map rot8cls: 
operands { - = 

}; 


0xD8; // 
{ +0=0xD8; 


11011000 

}; }; 




stack8 <= 


rot8cl 


op rot8crs { 
map rot 8crs : 
operands { - = 


0xD9; // 
{ +0=0xD9; 


11011001 

}; }; 




stack8 <= 


rot8cr 


}; 
// 

op rot81s { 
map rot81s : 
operands { - = 

}; 


OxDA; // 
{ +0=0xDA; 


11011010 

}; }; 




stack8 <= 


rot 81 


op rot8rs { 
map rot 8rs : 
operands { - = 


OxDB; // 
{ +0=0xDB; 


11011011 

}; }; 




stack8 <= 


rot8r 


// 

op casts { 

// // 1101110. 

map casts_uns: OxDC; // 11011100 
map casts_sig: OxDD; // 11011101 
operands { 

#1 = {+0=0xDC; +0[0:0]=#1; }; 

}; 

}; 


= 


casts <s±g> 
casts 0 
casts 1 



668 



Version "D" 



// 








op call { 








map call : 




OxDE; // 11011110 


= call # 


map call_ 


_i : 


OxFC; // 11111100 


= call (%I) 


map call_ 


-j : 


OxFD; // 11111101 


= call (%J) 


operands 


{ 






#1 


{ 


+0=0xDE; +1=#1[7:0]; +2= 


#1[15:8]; }; 


(%D = 

}; 


{ 


+0=0xFC; +0[0:0]=%1; }; 




}; 

op return { 








map return: 


OxDF; // 11011111 


= return 


operands 


{ 


~ = { +0=0xDF; }; }; 




}; 
// 








op int 1 








map int : 




OxEO; // 11100000 


= int <n> 


operands 


{ 






#1 = { 

}; 


+0 


=0xE0; +1=#1; }; 




}; 

op iret { 








map iret : 




OxEl; // 11100001 


= iret 


operands 


{ 


~ = { +0=0xEl; }; }; 




}; 
// 








op imrl { 








map imrl : 




0xE2; // 11100010 


= IMR load 


operands 


{ 






#1 


{ 


+0=0xE2; +1=#1[7:0]; }; 




}; 

operands 

}; 


{ 


- = { +0=0xE2; }; }; 




op ivtl { 








map ivtl : 




0xE3; // 11100011 


= IVT load 


operands 


{ 






#1 

}; 


{ 


+0=0xE3; +1=#1[7:0]; +2= 


#1[15:8]; }; 


}; 
// 









Version "D" 



669 



op flag_i { 










map flag_i_clr: 0xE4; 


// 11100100 




flag_i 0 


map flag_i_set: 0xE5; 


// 11100101 


= 


flag_i 1 


operands { 










#1 = { +0=0xE4; +0 [0 

}; 


0]=#1; }; 






}; 
// 










op flag_c { 










map flag_c_clr: 0xE6; 


// 11100110 




flag_c 0 


map flag_c_set: 0xE7; 


// 11100111 


= 


flag_c 1 


operands { 










#1 = { +0=0xE6; +0 [0 

}; 


0]=#1; }; 






}; 
// 










op in { 










map in_num_a : 0xE8 




// 11101000 


= 


in <n>, %A 


map in_num_b: 0xE9 




// 11101001 


— 


in <n>, %B 


map in_num_mi : OxEA 




// 11101010 




in <n>, (%I) 


map in_num_m j : OxEB 




// 11101011 




in <n>, (%J) 


operands { 










#1,%2 = { +0=0xE8; 


+0 [0 : 0] =%2; 


+1 


=#i; }; 


#1, (%2) = { +0 = 0xEA; 

}; 


+0 [0 : 0] =%2; 


+1 


=#i; }; 


}; 

op out { 










map out_a_num: OxEC 




// 11101100 





out %A, # 


map out_b_num: OxED 




// 11101101 


= 


out %B,# 


map out_mi_num: OxEE 




// 11101110 


— 


out 


map out_mi_num: OxEF 




// 11101111 




out (%J) , # 


operands { 










%1,#2 = { +0=0xEC; 


+0 [0 : 0] =%1; 


+1 


=#2; }; 


(%1) , #2 = { +0=0xEE; 

}; 


+0 [0 : 0] =%1; 


+1 


=#2; }; 


}; 
// 










op ifack_jump { 










map ifack_jump: OxFO; 


// 11110000 




jump if ack from device 


operands { 











670 



Version "D" 



#1,#2 

}; 


{ 


+0=0xF0; 


+1=#1; +2=#2[7:0]; +3=#2 [ 15 : 8 ] ; }; 


}; 

op ifack_call 


{ 






map ifack_call 


: OxFl; 


// 11110001 = call if ack from device 


operands { 








#1,#2 

}; 


{ 


+0=0xFl; 


+1=#1; +2=#2[7:0]; +3=#2[15:8]; }; 


}; 
// 








op cmpr { 








map cmpr : 




0xF2; 


// 11110010 = compare %A, %B 


operands { - 

}; 


■ = 


{ +0[7: 


0]=0xF2; }; }; 


op testr { 








map testr: 




0xF3; 


// 11110011 = test %A, %B 


operands { - 




{ +0[7: 


0]=0xF3; }; }; 


}; 
// 








op cmpi { 








map cmpi : 




0xF4; 


// 11110100 = compare (% I) , (%J) 


operands { - 

}; 


■ = 


{ +0[7: 


0]=0xF4; }; }; 


op testi { 








map testi: 




0xF5; 


// 11110101 = test (%I) , (%J) 


operands { - 


■ = 


{ +0[7: 


0]=0xF5; }; }; 


}; 
// 








op cmps { 








map cmps : 




0xF6; 


// 11110110 = compare stack 


operands { - 

}; 


■ = 


{ +0[7: 


0]=0xF6; }; }; 


op tests { 








map tests: 




0xF7; 


// 11110111 = test stack 


operands { - 




{ +0[7: 


0]=0xF7; }; }; 


}; 
// 








op cmp8i { 








map cmp8i: 




0xF8; 


// 11111000 = compare8 (%I) , (%J) 


operands { - 




{ +0[7: 


0]=0xF8; }; }; 



Version "D" 



671 



}; 

op test8i { 
map test8i: 
operands { - 


0xF9; 
- = { +0[7 


// 11111001 

0]=0xF9; }; } 


= tests (%I) , (%J) 

f 


}; 
// 

op cmp8s { 
map cmp8 s : 
operands { - 


OxFA; 
- = { +0[7 


// 11111010 

0]=0xFA; }; } 


= compare 8 stack 

f 


}; 

op test 8s { 
map test8s: 
operands { - 


OxFB; 
- = { +0[7 


// 11111011 

0]=0xFB; }; } 


= tests stack 

f 


}; 
// 

op stop { 
map stop: 
operands { - 

}; 


OxFF; 
- = { +0[7 


// 11111111 

0]=0xFF; }; } 


f 



11.15 Microcode 

« 

It follows the microcode listing, describing the opcode procedures. 
Listing 11.43. Microcode for TKGate. 



begin microcode @ 0 




// 




fetch : 




// IR[7:0] <= RAM[PC++], 


MPC <= IR[7:0] 


ir=select_bus_b ir=rank_i 


3 ir=register_load_byte_l ir=select_byte_l 


ram=select_bus_b ram=bus_ 


_write ram=p 


pc=dpl ctrl=load; 




// 




nop : 




// MPC <= ifetch 




addr=fetch jump=true; 




// 




cp_i_j : 




// J <= I, MPC <= # fetch 




j=select_bus_a j=rank_16 


j=register_load 



672 



Version "D" 





i=select_bus_a i=rank_16 


i 


=bus_write 




addr=fetch jump=true; 






cp_ 


_i_a : 

// A <= I, MPC <= # fetch 








a=select_bus_a a=rank_16 


a 


=register_load 




i=select_bus_a i=rank_16 


i 


=bus_write 




addr=fetch jump=true; 






cp_ 


i_b: 

// B <= J, MPC <= # fetch 








b=select_bus_a b=rank_16 


b 


=register_load 




i=select_bus_a i=rank_16 


i 


=bus_write 




addr=fetch jump=true; 






cp_ 


_i_sp : 








// SP <= J, MPC <= # fetch 






sp=select_bus_a sp=rank_ 


16 


sp=register_load 




i=select_bus_a i=rank_16 


i 


=bus_write 




addr=fetch jump=true; 






cp_ 


_i_bp : 








// BP <= J, MPC <= # fetch 






bp=select_bus_a bp=rank_ 


16 


bp=register_load 




i=select_bus_a i=rank_16 


i 


=bus_write 




addr=fetch jump=true; 






cp_ 


_i_c : 

// C <= I, MPC <= # fetch 








c=select_bus_a c=rank_16 


c 


=register_load 




i=select_bus_a i=rank_16 


i 


=bus_write 




addr=fetch jump=true; 






cp_ 


_i_f 1 : 








// FL <= I, MPC <= # fetch 






f l=select_bus_a fl=rank_ 


16 


f l=register_load 




i=select_bus_a i=rank_16 


i 


=bus_write 




addr=fetch jump=true; 






cp_ 


// I <= J, MPC <= # fetch 








i=select_bus_a i=rank_16 


i 


=register_load 




j=select_bus_a j=rank_16 


j 


=bus_write 




addr=fetch jump=true; 






cp_ 


_j_a: 

// A <= J, MPC <= # fetch 








a=select_bus_a a=rank_16 


a 


=register_load 




j=select_bus_a j=rank_16 


j 


=bus_write 



Version "D" 



673 





addr=fetch jump=true; 




cp_ 


_j_b: 






// B <= J, MPC <= # fetch 






b=select_bus_a b=rank_16 b 


=register_load 




j=select_bus_a j=rank_16 j 


=bus_write 




addr=fetch jump=true; 




cp_ 


_j_sp: 






// SP <= J, MPC <= # fetch 






sp=select_bus_a sp=rank_16 


sp=register_load 




j=select_bus_a j=rank_16 j 


=bus_write 




addr=fetch jump=true; 




cp_ 


_j_bp: 






// BP <= J, MPC <= # fetch 






bp=select_bus_a bp=rank_16 


bp=register_load 




j=select_bus_a j=rank_16 j 


=bus_write 




addr=fetch jump=true; 




cp_ 


_j_c: 






// C <= J, MPC <= # fetch 






c=select_bus_a c=rank_16 c 


=register_load 




j=select_bus_a j=rank_16 j 


=bus_write 




addr=fetch jump=true; 




cp_ 


-j_fl: 






// FL <= J, MPC <= # fetch 






f l=select_bus_a fl=rank_16 


f l=register_load 




j=select_bus_a j=rank_16 j 


=bus_write 




addr=fetch jump=true; 




cp_ 


_a_i : 






// I <= A, MPC <= # fetch 






i=select_bus_a i=rank_16 i 


=register_load 




a=select_bus_a a=rank_16 a 


=bus_write 




addr=fetch jump=true; 




cp_ 


_a_j : 






// J <= A, MPC <= # fetch 






j=select_bus_a j=rank_16 j 


=register_load 




a=select_bus_a a=rank_16 a 


=bus_write 




addr=fetch jump=true; 




cp_ 


_a_b : 






// B <= A, MPC <= # fetch 






b=select_bus_a b=rank_16 b 


=register_load 




a=select_bus_a a=rank_16 a 


=bus_write 




addr=fetch jump=true; 





674 



Version "D" 



cp_ 


_a_sp : 






// SP <= A, MPC <= # fetch 






sp=select_bus_a sp=rank_16 


sp=register_load 




a=select_bus_a a=rank_16 a 


=bus_write 




addr=f etch jump=true; 




cp_ 


_a_bp : 






// BP <= A, MPC <= # fetch 






bp=select_bus_a bp=rank_16 


bp=register_load 




a=select_bus_a a=rank_16 a 


=bus_write 




addr=fetch jump=true; 




cp_ 


_a_c : 






// C <= A, MPC <= # fetch 






c=select_bus_a c=rank_16 c 


=register_load 




a=select_bus_a a=rank_16 a 


=bus_write 




addr=fetch jump=true; 




cp_ 


_a_f 1 : 






// FL <= A, MPC <= # fetch 






f l=select_bus_a fl=rank_16 


f l=register_load 




a=select_bus_a a=rank_16 a 


=bus_write 




addr=fetch jump=true; 




cp_ 


_b_i : 






// I <= B, MPC <= # fetch 






i=select_bus_a i=rank_16 i 


=register_load 




b=select_bus_a b=rank_16 b 


=bus_write 




addr=fetch jump=true; 




cp_ 


_b_j: 






// J <= B, MPC <= # fetch 






j=select_bus_a j=rank_16 j 


=register_load 




b=select_bus_a b=rank_16 b 


=bus_write 




addr=fetch jump=true; 




cp_ 


_b_a : 






// A <= B, MPC <= # fetch 






a=select_bus_a a=rank_16 a 


=register_load 




b=select_bus_a b=rank_16 b 


=bus_write 




addr=fetch jump=true; 




cp_ 


_b_sp : 






// SP <= B, MPC <= # fetch 






sp=select_bus_a sp=rank_16 


sp=register_load 




b=select_bus_a b=rank_16 b 


=bus_write 




addr=fetch jump=true; 




cp_ 


_b_bp : 





Version "D" 



675 





// BP <= B, MPC <= # fetch 






bp=select_bus_a bp=rank_16 


bp=register_load 




b=select_bus_a b=rank_16 b= 


=bus_write 




addr=fetch jump=true; 




cp_ 


_b_c : 






// C <= B, MPC <= # fetch 






c=select_bus_a c=rank_16 c= 


=register_load 




b=select_bus_a b=rank_16 b= 


=bus_write 




addr=fetch jump=true; 




cp_ 


_b_f 1 : 






// FL <= B, MPC <= # fetch 






f l=select_bus_a fl=rank_16 


f l=register_load 




b=select_bus_a b=rank_16 b= 


=bus_write 




addr=fetch jump=true; 




cp_ 


_sp_i : 






// I <= SP, MPC <= # fetch 






i=select_bus_a i=rank_16 i= 


=register_load 




sp=select_bus_a sp=rank_16 


sp=bus_write 




addr=fetch jump=true; 




cp_ 


_sp_ j : 






// J <= SP, MPC <= # fetch 






j=select_bus_a j=rank_16 j= 


=register_load 




sp=select_bus_a sp=rank_16 


sp=bus_write 




addr=fetch jump=true; 




cp_ 


_sp_a : 






// A <= SP, MPC <= # fetch 






a=select_bus_a a=rank_16 a= 


=register_load 




sp=select_bus_a sp=rank_16 


sp=bus_write 




addr=fetch jump=true; 




cp_ 


_sp_b : 






// B <= SP, MPC <= # fetch 






b=select_bus_a b=rank_16 b= 


=register_load 




sp=select_bus_a sp=rank_16 


sp=bus_write 




addr=fetch jump=true; 




cp_ 


_sp_bp : 






// BP <= SP, MPC <= # fetch 






bp=select_bus_a bp=rank_16 


bp=register_load 




sp=select_bus_a sp=rank_16 


sp=bus_write 




addr=fetch jump=true; 




cp_ 


_sp_c : 






// C <= SP, MPC <= # fetch 





676 



Version "D" 





c=select_bus_a c=rank_16 c= 


=register_load 




sp=select_bus_a sp=rank_16 


sp=bus_write 




addr=fetch jump=true; 




cp_ 


_sp_f 1 : 

// FL <= SP, MPC <= # fetch 






f l=select_bus_a fl=rank_16 


f l=register_load 




sp=select_bus_a sp=rank_16 


sp=bus_write 




addr=fetch jump=true; 




cp_ 


_bp_i : 

// I <= BP, MPC <= # fetch 






i=select_bus_a i=rank_16 i= 


=register_load 




bp=select_bus_a bp=rank_16 


bp=bus_write 




addr=fetch jump=true; 




cp_ 


_bp_ j : 

// J <= BP, MPC <= ifetch 






j=select_bus_a j=rank_16 j= 


=register_load 




bp=select_bus_a bp=rank_16 


bp=bus_write 




addr=fetch jump=true; 




cp_ 


_bp_a : 

// A <= BP, MPC <= # fetch 






a=select_bus_a a=rank_16 a= 


=register_load 




bp=select_bus_a bp=rank_16 


bp=bus_write 




addr=fetch jump=true; 




cp_ 


_bp_b : 

// B <= BP, MPC <= # fetch 






b=select_bus_a b=rank_16 b= 


=register_load 




bp=select_bus_a bp=rank_16 


bp=bus_write 




addr=fetch jump=true; 




cp_ 


_bp_sp : 

// SP <= BP, MPC <= # fetch 






sp=select_bus_a sp=rank_16 


sp=register_load 




bp=select_bus_a bp=rank_16 


bp=bus_write 




addr=fetch jump=true; 




cp_ 


_bp_c : 

// C <= BP, MPC <= # fetch 






c=select_bus_a c=rank_16 c= 


=register_load 




bp=select_bus_a bp=rank_16 


bp=bus_write 




addr=fetch jump=true; 




cp_ 


_bp_f 1 : 

// FL <= BP, MPC <= # fetch 






f l=select_bus_a fl=rank_16 


f l=register_load 



Version "D" 



677 





bp=select_bus_a bp=rank_16 


bp=bus_write 




addr=fetch jump=true; 




cp_ 


_c_i : 

// I <= C, MPC <= # fetch 






i=select_bus_a i=rank_16 i 


=register_load 




c=select_bus_a c=rank_16 c 


=bus_write 




addr=f etch jump=true; 




cp_ 


_c_j : 

// J <= C, MPC <= # fetch 






j=select_bus_a j=rank_16 j 


=register_load 




c=select_bus_a c=rank_16 c 


=bus_write 




addr=fetch jump=true; 




cp_ 


_c_a : 

// A <= C, MPC <= # fetch 






a=select_bus_a a=rank_16 a 


=register_load 




c=select_bus_a c=rank_16 c 


=bus_write 




addr=fetch jump=true; 




cp_ 


_c_b : 

// B <= C, MPC <= # fetch 






b=select_bus_a b=rank_16 b 


=register_load 




c=select_bus_a c=rank_16 c 


=bus_write 




addr=fetch jump=true; 




cp_ 


_c_sp : 

// SP <= C, MPC <= # fetch 






sp=select_bus_a sp=rank_16 


sp=register_load 




c=select_bus_a c=rank_16 c 


=bus_write 




addr=fetch jump=true; 




cp_ 


_c_bp : 

// BP <= C, MPC <= # fetch 






bp=select_bus_a bp=rank_16 


bp=register_load 




c=select_bus_a c=rank_16 c 


=bus_write 




addr=fetch jump=true; 




cp_ 


_c_fl: 

// FL <= C, MPC <= # fetch 






f l=select_bus_a fl=rank_16 


f l=register_load 




c=select_bus_a c=rank_16 c 


=bus_write 




addr=fetch jump=true; 




cp_ 


_fl_i : 

// I <= FL, MPC <= ifetch 






i=select_bus_a i=rank_16 i 


=register_load 




f l=select_bus_a fl=rank_16 


f l=bus_write 



678 



Version "D" 





addr=fetch jump=true; 






cp_ 


-fl_j: 

// J <= FL, MPC <= # fetch 

j=select_bus_a j=rank_16 j=register_load 
f l=select_bus_a fl=rank_16 fl=bus_write 
addr=fetch jump=true; 






cp_ 


_fl_a: 

// A <= FL, MPC <= #fetch 

a=select_bus_a a=rank_16 a=register_load 
f l=select_bus_a fl=rank_16 fl=bus_write 
addr=fetch jump=true; 






cp_ 


_fl_b: 

// B <= FL, MPC <= # fetch 

b=select_bus_a b=rank_16 b=register_load 
f l=select_bus_a fl=rank_16 fl=bus_write 
addr=fetch jump=true; 






cp_ 


_f l_sp : 

// SP <= FL, MPC <= # fetch 

sp=select_bus_a sp=rank_16 sp=register_load 
f l=select_bus_a fl=rank_16 fl=bus_write 
addr=fetch jump=true; 






cp_ 


_f l_bp : 

// BP <= FL, MPC <= # fetch 

bp=select_bus_a bp=rank_16 bp=register_load 
f l=select_bus_a fl=rank_16 fl=bus_write 
addr=fetch jump=true; 






cp_ 


_fl_c: 

// C <= FL, MPC <= # fetch 

c=select_bus_a c=rank_16 c=register_load 
f l=select_bus_a fl=rank_16 fl=bus_write 
addr=fetch jump=true; 






cp_ 


_num_i : 

// I [7:0] <= RAM[PC++] 








i=select_bus_a i=rank_8 i=register_load_byte_l 


i=select_ 


_byte_l 




ram=select_bus_a ram=bus_write ram=p pc=dpl; 








// I [15: 8] <= RAM[PC++], MPC <= # fetch 








i=select_bus_a i=rank_8 i=register_load_byte_2 


i=select_ 


_byte_2 




ram=select_bus_a ram=bus_write ram=p pc=dpl 








addr=fetch jump=true; 






cp_ 


_num_j : 

// J [7:0] <= RAM[PC++] 







Version "D" 



679 





j=select_bus_a j=rank_8 j=register_load_byte_ 


1 


j = 


select. 


_byte_ 


,1 




ram=select_bus_a ram=bus_write ram=p pc=dpl; 














// J [15: 8] <= RAM[PC++], MPC <= # fetch 














j=select_bus_a j=rank_8 j=register_load_byte_ 


_2 


j = 


select. 


_byte_ 


,2 




ram=select_bus_a ram=bus_write ram=p pc=dpl 














addr=fetch jump=true; 












cp_ 


_num_a : 

// A [7:0] <= RAM[PC++] 














a=select_bus_a a=rank_8 a=register_load_byte_ 


1 


a= 


select. 


_byte_ 


,1 




ram=select_bus_a ram=bus_write ram=p pc=dpl; 














// A [15: 8] <= RAM[PC++] , MPC <= # fetch 














a=select_bus_a a=rank_8 a=register_load_byte_ 


_2 


a = 


select. 


_byte_ 


,2 




ram=select_bus_a ram=bus_write ram=p pc=dpl 














addr=fetch jump=true; 












cp_ 


_num_b : 

// B[7:0] <= RAM[PC++] 














b=select_bus_a b=rank_8 b=register_load_byte_ 


1 


b= 


select. 


_byte_ 


,1 




ram=select_bus_a ram=bus_write ram=p pc=dpl; 














// B[15:8] <= RAM[PC++] , MPC <= # fetch 














b=select_bus_a b=rank_8 b=register_load_byte_ 


_2 


b= 


select. 


_byte_ 


,2 




ram=select_bus_a ram=bus_write ram=p pc=dpl 














addr=fetch jump=true; 












cp_ 


_mi_a : 

// A [7:0] <= RAM [I] 














a=select_bus_a a=rank_8 a=register_load_byte_ 


1 


a= 


select. 


_byte_ 


,1 




ram=select_bus_a ram=bus_write ram=i; 














// A [15: 8] <= RAM[I+1], MPC <= # fetch 














a=select_bus_a a=rank_8 a=register_load_byte_ 


_2 


a= 


select. 


_byte_ 


,2 




ram=select_bus_a ram=bus_write ram=i i=qpl 














addr=fetch jump=true; 












cp_ 


_mi_b : 

// B[7:0] <= RAM [I] 














b=select_bus_a b=rank_8 b=register_load_byte_ 


1 


b= 


select. 


_byte_ 


,1 




ram=select_bus_a ram=bus_write ram=i; 














// B[15:8] <= RAM[I+1] , MPC <= # fetch 














b=select_bus_a b=rank_8 b=register_load_byte_ 


_2 


b= 


select. 


_byte_ 


,2 




ram=select_bus_a ram=bus_write ram=i i=qpl 














addr=fetch jump=true; 












cp_ 


_m j_a : 

// A[7:0] <= RAM [J] 














a=select_bus_a a=rank_8 a=register_load_byte_ 


1 


a= 


select. 


_byte_ 


,1 



680 



Version "D" 



ram=select_bus_a ram=bus_write ram=j; 
// A [15: 8] <= RAM[J+1] , MPC <= # fetch 

a=select_bus_a a=rank_8 a=register_load_byte_2 a=select_byte_2 
ram=select_bus_a ram=bus_write ram=j j=qpl 
addr=fetch jump=true; 
cp_m j_b : 

// B[7:0] <= RAM [J] 

b=select_bus_a b=rank_8 b=register_load_byte_l b=select_byte_l 
ram=select_bus_a ram=bus_write ram=j; 
// B[15:8] <= RAM[J+1] , MPC <= # fetch 

b=select_bus_a b=rank_8 b=register_load_byte_2 b=select_byte_2 
ram=select_bus_a ram=bus_write ram=j j=qpl 
addr=fetch jump=true; 
cp_a_mi : 

// RAM [I] <= A[7:0] 
ram=select_bus_a ram=load ram=i 

a=select_bus_a a=rank_8 a=select_byte_l a=bus_write; 
// RAM[I+1] <= A [15: 8], MPC <= # fetch 

ram=select_bus_a ram=load ram=i i=qpl 
a=select_bus_a a=rank_8 a=select_byte_2 a=bus_write 
addr=fetch jump=true; 
cp_a_m j : 

// RAM [J] <= A[7:0] 
ram=select_bus_a ram=load ram=j 

a=select_bus_a a=rank_8 a=select_byte_l a=bus_write; 
// RAM[J+1] <= A[15:8], MPC <= # fetch 

ram=select_bus_a ram=load ram=j j=qpl 
a=select_bus_a a=rank_8 a=select_byte_2 a=bus_write 
addr=fetch jump=true; 
cp_b_mi : 

// RAM [I] <= B[7:0] 
ram=select_bus_a ram=load ram=i 

b=select_bus_a b=rank_8 b=select_byte_l b=bus_write; 
// RAM[I+1] <= B[15:8], MPC <= # fetch 

ram=select_bus_a ram=load ram=i i=qpl 
b=select_bus_a b=rank_8 b=select_byte_2 b=bus_write 
addr=fetch jump=true; 
cp_b_m j : 

// RAM[J] <= B[7:0] 
ram=select_bus_a ram=load ram=j 

b=select_bus_a b=rank_8 b=select_byte_l b=bus_write; 



Version "D" 



681 



// RAM[J+1] <= B[15:8], MPC <= # fetch 

ram=select_bus_a ram=load ram=j j=qpl 
b=select_bus_a b=rank_8 b=select_byte_2 b=bus_write 
addr=fetch jump=true; 
cp_num_mi : 

// TMP[7:0] <= RAM[PC++] 

tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_l tmp=select_byte_l 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 
// TMP[15:8] <= RAM[PC++] 

tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_2 tmp=select_byte_2 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 
// RAM [I] <= TMP[7:0] 

ram=select_bus_a ram=load ram=i 

tmp=select_bus_a tmp=rank_8 tmp=select_byte_l tmp=bus_write ; 
// RAM[I+1] <= TMP[15:8], MPC <= # fetch 

ram=select_bus_a ram=load ram=i i=qpl 

tmp=select_bus_a tmp=rank_8 tmp=select_byte_2 tmp=bus_write 
addr=fetch jump=true; 
cp_num_m j : 

// TMP[7:0] <= RAM[PC++] 

tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_l tmp=select_byte_l 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 
// TMP[15:8] <= RAM[PC++] 

tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_2 tmp=select_byte_2 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 
// RAM [J] <= TMP[7:0] 

ram=select_bus_a ram=load ram=j 

tmp=select_bus_a tmp=rank_8 tmp=select_byte_l tmp=bus_write ; 
// RAM[J+1] <= TMP[15:8], MPC <= # fetch 

ram=select_bus_a ram=load ram=j j=qpl 

tmp=select_bus_a tmp=rank_8 tmp=select_byte_2 tmp=bus_write 
addr=fetch jump=true; 
cp_mi_mj : 

// TMP[7:0] <= RAM [I] 

tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_l tmp=select_byte_l 
ram=select_bus_a ram=bus_write ram=i; 
// TMP[15:8] <= RAM[I+1] 

tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_2 tmp=select_byte_2 
ram=select_bus_a ram=bus_write ram=i i=qpl; 
// RAM [J] <= TMP[7:0] 

ram=select_bus_a ram=load ram=j 



682 



Version "D" 





tmp=select_bus_a tmp=rank_8 tmp=select_byte_ 


1 


tmp=bus_write ; 






// RAM[J+1] <= TMP[15:8], MPC <= # fetch 










ram=select_bus_a ram=load ram=j j=qpl 










tmp=select_bus_a tmp=rank_8 tmp=select_byte_ 


_2 


tmp=bus_write 






addr=fetch jump=true; 








cp_ 


_m j_mi : 










// TMP[7:0] <= RAM [J] 










tmp=select_bus_a tmp=rank_8 tmp=register_load_ 


_byte_l tmp=select_ 


_byte_l 




ram=select_bus_a ram=bus_write ram=j; 










// TMP[15:8] <= RAM[J+1] 










tmp=select_bus_a tmp=rank_8 tmp=register_load_ 


_byte_2 tmp=select_ 


_byte_2 




ram=select_bus_a ram=bus_write ram=j j=qpl; 










// RAM [I] <= TMP[7:0] 










ram=select_bus_a ram=load ram=i 










tmp=select_bus_a tmp=rank_8 tmp=select_byte_ 


1 


tmp=bus_write ; 






// RAM[I+1] <= TMP[15:8], MPC <= # fetch 










ram=select_bus_a ram=load ram=i i=qpl 










tmp=select_bus_a tmp=rank_8 tmp=select_byte_ 


_2 


tmp=bus_write 






addr=fetch jump=true; 








cpi 


3_num_i : 










// I <= RAM[PC++], MPC <= # fetch 










i=select_bus_a i=register_load 










ram=select_bus_a ram=bus_write ram=p pc=dpl 










addr=fetch jump=true; 








cpi 


3_num_j : 










// J <= RAM[PC++], MPC <= # fetch 










j=select_bus_a j=register_load 










ram=select_bus_a ram=bus_write ram=p pc=dpl 










addr=fetch jump=true; 








cpi 


3_num_a : 










// A <= RAM[PC++] , MPC <= # fetch 










a=select_bus_a a=register_load 










ram=select_bus_a ram=bus_write ram=p pc=dpl 










addr=fetch jump=true; 








cpi 


3_num_b : 










// B <= RAM[PC++], MPC <= # fetch 










b=select_bus_a b=register_load 










ram=select_bus_a ram=bus_write ram=p pc=dpl 










addr=fetch jump=true; 








cpi 


3_mi_a : 










// A <= RAM [I], MPC <= # fetch 









Version "D" 



683 



a=select_bus_a a=register_load 
ram=select_bus_a ram=bus_write ram=i 
addr=fetch jump=true; 

cp8_mi_b : 

// B <= RAM [I], MPC <= # fetch 
b=select_bus_a b=register_load 
ram=select_bus_a ram=bus_write ram=i 
addr=fetch jump=true; 

cp8_m j_a : 

// A <= RAM [J], MPC <= # fetch 
a=select_bus_a a=register_load 
ram=select_bus_a ram=bus_write ram=j 
addr=fetch jump=true; 

cp8_m j_b : 

// B <= RAM [J], MPC <= # fetch 
b=select_bus_a b=register_load 
ram=select_bus_a ram=bus_write ram=j 
addr=fetch jump=true; 

cp8_a_mi : 

// RAM [I] <= B, MPC <= # fetch 
ram=select_bus_a ram=load ram=i 
a=select_bus_a a=bus_write 
addr=fetch jump=true; 

cp8_a_mj : 

// RAM [J] <= B, MPC <= # fetch 
ram=select_bus_a ram=load ram=j 
a=select_bus_a a=bus_write 
addr=fetch jump=true; 

cp8_b_mi : 

// RAM [I] <= B, MPC <= # fetch 
ram=select_bus_a ram=load ram=i 
b=select_bus_a b=bus_write 
addr=fetch jump=true; 

cp8_b_mj : 

// RAM [J] <= B, MPC <= # fetch 
ram=select_bus_a ram=load ram=j 
b=select_bus_a b=bus_write 
addr=fetch jump=true; 

cp8_num_mi : 

// TMP <= RAM[PC++] 
tmp=select_bus_a tmp=register_load 



684 



Version "D" 



ram=select_bus_a ram=bus_write ram=p pc 


=dpl; 




// RAM [I] <= TMP , MPC <= # fetch 






ram=select_bus_a ram=load ram=i 






tmp=select_bus_a tmp=bus_write 






addr=fetch jump=true; 






cp8_num_m j : 






// TMP <= RAM[PC++] 






tmp=select_bus_a tmp=register_load 






ram=select_bus_a ram=bus_write ram=p pc 


=dpl; 




// RAM [J] <= TMP, MPC <= # fetch 






ram=select_bus_a ram=load ram=j 






tmp=select_bus_a tmp=bus_write 






addr=fetch jump=true; 






cp8_mi_m j : 






// TMP <= RAM [I ] 






tmp=select_bus_a tmp=register_load 






ram=select_bus_a ram=bus_write ram=i; 






// RAM[J] <= TMP, MPC <= # fetch 






ram=select_bus_a ram=load ram=j 






tmp=select_bus_a tmp=bus_write 






addr=fetch jump=true; 






cp8_m j_mi : 






// TMP <= RAM[J] 






tmp=select_bus_a tmp=register_load 






ram=select_bus_a ram=bus_write ram=j; 






// RAM [I ] <= TMP, MPC <= # fetch 






ram=select_bus_a ram=load ram=i 






tmp=select_bus_a tmp=bus_write 






addr=fetch jump=true; 






push_i : 






// RAM[ — SP] <= I [15: 8] 






ram=select_bus_a ram=load ram=s sp=qml 


sp=qup 




i=select_bus_a i=rank_8 i=select_byte_2 


i=bus_ 


_write ; 


// RAM[ — SP] <= I [7:0], MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml 


sp=qup 




i=select_bus_a i=rank_8 i=select_byte_l 


i=bus_ 


_write 


addr=fetch jump=true; 






push_j : 






// RAM[ — SP] <= J[15:8] 






ram=select_bus_a ram=load ram=s sp=qml 


sp=qup 




j=select_bus_a j=rank_8 j=select_byte_2 


j=bus_ 


_write ; 



Version "D" 



685 



// RAM[ — SP] <= J [7:0], MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml sp 


=qup 




j=select_bus_a j=rank_8 j=select_byte_l j 


=bus_ 


_write 


addr=fetch jump=true; 






push_a : 






// RAM[ — SP] <= A[15:8] 






ram=select_bus_a ram=load ram=s sp=qml sp 


=qup 




a=select_bus_a a=rank_8 a=select_byte_2 a 


=bus_ 


_write ; 


// RAM[ — SP] <= A[7:0], MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml sp 


=qup 




a=select_bus_a a=rank_8 a=select_byte_l a 


=bus_ 


_write 


addr=fetch jump=true; 






push_b : 






// RAM[ — SP] <= B[15:8] 






ram=select_bus_a ram=load ram=s sp=qml sp 


=qup 




b=select_bus_a b=rank_8 b=select_byte_2 b 


=bus_ 


_write ; 


// RAM[ — SP] <= B[7:0], MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml sp 


=qup 




b=select_bus_a b=rank_8 b=select_byte_l b 


=bus_ 


_write 


addr=fetch jump=true; 






push_bp : 






// RAM[ — SP] <= BP [15: 8] 






ram=select_bus_a ram=load ram=s sp=qml sp 


=qup 




bp=select_bus_a bp=rank_8 bp=select_byte_ 


2 bp= 


=bus_write ; 


// RAM[ — SP] <= BP [7:0], MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml sp 


=qup 




bp=select_bus_a bp=rank_8 bp=select_byte_ 


1 bp= 


=bus_write 


addr=fetch jump=true; 






push_sp : 






// RAM[ — SP] <= SP[15:8] 






ram=select_bus_a ram=load ram=s sp=qml sp 


=qup 




sp=select_bus_a sp=rank_8 sp=select_byte_ 


2 sp= 


=bus_write ; 


// RAM[ — SP] <= SP[7:0] , MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml sp 


=qup 




sp=select_bus_a sp=rank_8 sp=select_byte_ 


1 sp= 


=bus_write 


addr=fetch jump=true; 






push_c : 






// RAM[ — SP] <= C[15:8] 






ram=select_bus_a ram=load ram=s sp=qml sp 


=qup 




c=select_bus_a c=rank_8 c=select_byte_2 c 


=bus_ 


_write ; 


// RAM[ — SP] <= C[7:0], MPC <= # fetch 







686 



Version "D" 



ram=select_bus_a ram=load ram=s sp=qml sp=qup 












c=select_bus_a c=rank_8 c=select_byte_l c=bus_ 


_write 








addr=fetch jump=true; 












push_f 1 : 












// RAM[ — SP] <= FL[15:8] 












ram=select_bus_a ram=load ram=s sp=qml sp=qup 












f l=select_bus_a fl=rank_8 f l=select_byte_2 fl= 


=bus_ 


write ; 








// RAM[ — SP] <= FL[7:0], MPC <= # fetch 












ram=select_bus_a ram=load ram=s sp=qml sp=qup 












f l=select_bus_a fl=rank_8 f l=select_byte_l fl= 


=bus_ 


write 








addr=fetch jump=true; 












push_num : 












// TMP[7:0] <= RAM[PC++] 












tmp=select_bus_a tmp=rank_8 tmp=register_load_ 


_byte 


_1 tmp= 


select. 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=p pc=dpl; 












// TMP[15:8] <= RAM[PC++] 












tmp=select_bus_a tmp=rank_8 tmp=register_load_ 


_byte 


_2 tmp= 


select. 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=p pc=dpl; 












// RAM[ — SP] <= TMP[15:8] 












ram=select_bus_a ram=load ram=s sp=qml sp=qup 












tmp=select_bus_a tmp=rank_8 tmp=select_byte_2 


tmp= 


bus_write ; 






// RAM[ — SP] <= TMP[7:0], MPC <= # fetch 












ram=select_bus_a ram=load ram=s sp=qml sp=qup 












tmp=select_bus_a tmp=rank_8 tmp=select_byte_l 


tmp= 


bus_write 






addr=fetch jump=true; 












push_mi : 












// TMP[7:0] <= RAM [I] 












tmp=select_bus_a tmp=rank_8 tmp=register_load_ 


_byte 


_1 tmp= 


select. 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=i; 












// TMP[15:8] <= RAM[I+1] 












tmp=select_bus_a tmp=rank_8 tmp=register_load_ 


_byte 


_2 tmp= 


select. 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=i i=qpl; 












// RAM[ — SP] <= TMP[15:8] 












ram=select_bus_a ram=load ram=s sp=qml sp=qup 












tmp=select_bus_a tmp=rank_8 tmp=select_byte_2 


tmp= 


bus_write ; 






// RAM[ — SP] <= TMP[7:0], MPC <= # fetch 












ram=select_bus_a ram=load ram=s sp=qml sp=qup 












tmp=select_bus_a tmp=rank_8 tmp=select_byte_l 


tmp= 


bus_write 






addr=fetch jump=true; 












push_m j : 












// TMP[7:0] <= RAM [J] 













Version "D" 



687 



tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_l tmp=select_byte_l 
ram=select_bus_a ram=bus_write ram=j; 
// TMP[15:8] <= RAM[J+1] 

tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_2 tmp=select_byte_2 
ram=select_bus_a ram=bus_write ram=j j=qpl; 
// RAM[ — SP] <= TMP[15:8] 

ram=select_bus_a ram=load ram=s sp=qml sp=qup 

tmp=select_bus_a tmp=rank_8 tmp=select_byte_2 tmp=bus_write ; 
// RAM[ — SP] <= TUP [1:0], MPC <= # fetch 

ram=select_bus_a ram=load ram=s sp=qml sp=qup 
tmp=select_bus_a tmp=rank_8 tmp=select_byte_l tmp=bus_write 
addr=fetch jump=true; 
pop_i : 

// I [7:0] <= RAM[SP++] 

i=select_bus_a i=rank_8 i=register_load_byte_l i=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=dpl; 
// I [15: 8] <= RAM[SP++] , MPC <= # fetch 

i=select_bus_a i=rank_8 i=register_load_byte_2 i=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=dpl 
addr=fetch jump=true; 
pop_j : 

// J [7:0] <= RAM[SP++] 

j=select_bus_a j=rank_8 j=register_load_byte_l j=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=dpl; 
// J[15:8] <= RAM[SP++] , MPC <= # fetch 

j=select_bus_a j=rank_8 j=register_load_byte_2 j=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=dpl 
addr=fetch jump=true; 
pop_a : 

// A [7:0] <= RAM[SP++] 

a=select_bus_a a=rank_8 a=register_load_byte_l a=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=dpl; 
// A[15:8] <= RAM[SP++], MPC <= # fetch 

a=select_bus_a a=rank_8 a=register_load_byte_2 a=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=dpl 
addr=fetch jump=true; 
pop_b : 

// B[7:0] <= RAM[SP++] 

b=select_bus_a b=rank_8 b=register_load_byte_l b=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=dpl; 
// B[15:8] <= RAM[SP++] , MPC <= # fetch 



688 



Version "D" 



b=select_bus_a b=rank_8 b=register_load_byte_2 b=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=dpl 
addr=fetch jump=true; 
pop_bp : 

// BP [7:0] <= RAM[SP++] 

bp=select_bus_a bp=rank_8 bp=register_load_byte_l bp=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=dpl; 
// BP [15: 8] <= RAM[SP++] , MPC <= # fetch 

bp=select_bus_a bp=rank_8 bp=register_load_byte_2 bp=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=dpl 
addr=fetch jump=true; 
pop_sp : 

// SP[7:0] <= RAM[SP++] 

sp=select_bus_a sp=rank_8 sp=register_load_byte_l sp=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=dpl; 
// SP[15:8] <= RAM[SP++] , MPC <= # fetch 

sp=select_bus_a sp=rank_8 sp=register_load_byte_2 sp=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=dpl 
addr=fetch jump=true; 
pop_c : 

// C[7:0] <= RAM[SP++] 

c=select_bus_a c=rank_8 c=register_load_byte_l c=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=dpl; 
// C[15:8] <= RAM[SP++] , MPC <= # fetch 

c=select_bus_a c=rank_8 c=register_load_byte_2 c=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=dpl 
addr=fetch jump=true; 
pop_f 1 : 

// FL[7:0] <= RAM[SP++] 

f l=select_bus_a fl=rank_8 f l=register_load_byte_l f l=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=dpl; 
// FL[15:8] <= RAM[SP++], MPC <= # fetch 

f l=select_bus_a fl=rank_8 f l=register_load_byte_2 f l=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=dpl 
addr=fetch jump=true; 
pop_mi : 

// TMP[7:0] <= RAM[SP++] 

tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_l tmp=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=dpl; 
// TMP[15:8] <= RAM[SP++], MPC <= # fetch 

tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_2 tmp=select_byte_2 



Version "D" 



689 



ram=select_bus_a ram=bus_write ram=s sp=dpl; 






// RAM [I] <= TMP[7:0] 






ram=select_bus_a ram=load ram=i 






tmp=select_bus_a tmp=rank_8 tmp=select_byte_l 


tmp=bus_write ; 




// RAM[I+1] <= TMP[15:8], MPC <= # fetch 






ram=select_bus_a ram=load ram=i i=qpl 






tmp=select_bus_a tmp=rank_8 tmp=select_byte_2 


tmp=bus_write 




addr=fetch jump=true; 






pop_m j : 






// TMP[7:0] <= RAM[SP++] 






tmp=select_bus_a tmp=rank_8 tmp=register_load_ 


_byte_l tmp=select_ 


_byte_l 


ram=select_bus_a ram=bus_write ram=s sp=dpl; 






// TMP[15:8] <= RAM[SP++], MPC <= # fetch 






tmp=select_bus_a tmp=rank_8 tmp=register_load_ 


_byte_2 tmp=select_ 


_byte_2 


ram=select_bus_a ram=bus_write ram=s sp=dpl; 






// RAM [J] <= TMP[7:0] 






ram=select_bus_a ram=load ram=j 






tmp=select_bus_a tmp=rank_8 tmp=select_byte_l 


tmp=bus_write ; 




// RAM[J+1] <= TMP[15:8], MPC <= # fetch 






ram=select_bus_a ram=load ram=j j=qpl 






tmp=select_bus_a tmp=rank_8 tmp=select_byte_2 


tmp=bus_write 




addr=fetch jump=true; 






push8_i : 






// RAM[ — SP] <= I, MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml sp=qup 






i=select_bus_a i=bus_write 






addr=fetch jump=true; 






push8_j : 






// RAM[ — SP] <= J, MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml sp=qup 






j=select_bus_a j=bus_write 






addr=fetch jump=true; 






push8_a : 






// RAM[ — SP] <= A, MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml sp=qup 






a=select_bus_a a=bus_write 






addr=fetch jump=true; 






push8_b : 






// RAM[ — SP] <= B, MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml sp=qup 






b=select_bus_a b=bus_write 







690 



Version "D" 



addr= fetch jump=true; 






push8_bp : 






// RAM[ — SP] <= BP, MFC <= # fetch 






ram=select_bus_a ram=load ram=s sp= 


=qml 


sp=qup 


bp=select_bus_a bp=bus_write 






addr=fetch jump=true; 






push8_sp : 






// RAM[ — SP] <= SP, MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp= 


=qml 


sp=qup 


sp=select_bus_a sp=bus_write 






addr=fetch jump=true; 






push8_c : 






// RAM[ — SP] <= C, MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp= 


=qml 


sp=qup 


c=select_bus_a c=bus_write 






addr=fetch jump=true; 






push8_f 1 : 






// RAM[ — SP] <= FL, MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp= 


=qml 


sp=qup 


f l=select_bus_a fl=bus_write 






addr=fetch jump=true; 






push8_num : 






// TMP <= RAM[PC++] 






tmp=select_bus_a tmp=register_load 






ram=select_bus_a ram=bus_write ram= 


=p pc 


=dpl ; 


// RAM[ — SP] <= TMP, MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp= 


=qml 


sp=qup 


tmp=select_bus_a tmp=bus_write 






addr=fetch jump=true; 






push8_mi : 






// TMP <= RAM [I] 






tmp=select_bus_a tmp=register_load 






ram=select_bus_a ram=bus_write ram= 


=i; 




// RAM[ — SP] <= TMP, MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp= 


=qml 


sp=qup 


tmp=select_bus_a tmp=bus_write 






addr=fetch jump=true; 






push8_mj : 






// TMP <= RAM [J] 






tmp=select_bus_a tmp=register_load 






ram=select_bus_a ram=bus_write ram= 


=j; 





Version "D" 



691 





// RAM[ — SP] <= TMP , MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp= 


qml sp=qup 




tmp=select_bus_a tmp=bus_write 








addr=fetch jump=true; 






pop<: 


3_i : 








// I <= RAM[SP++], MPC <= # fetch 








i=select_bus_a i=register_load 








ram=select_bus_a ram=bus_write ram= 


s 


sp=dpl 




addr=fetch jump=true; 






pop<: 










// J <= RAM[SP++], MPC <= # fetch 








j=select_bus_a j=register_load 








ram=select_bus_a ram=bus_write ram= 


s 


sp=dpl 




addr=fetch jump=true; 






pop? 


i_a: 








// A <= RAM[SP++] , MPC <= # fetch 








a=select_bus_a a=register_load 








ram=select_bus_a ram=bus_write ram= 


s 


sp=dpl 




addr=fetch jump=true; 






pop<: 


3_b: 








// B <= RAM[SP++], MPC <= # fetch 








b=select_bus_a b=register_load 








ram=select_bus_a ram=bus_write ram= 


s 


sp=dpl 




addr=fetch jump=true; 






pop<: 


3_bp : 








// BP <= RAM[SP++], MPC <= # fetch 








bp=select_bus_a bp=register_load 








ram=select_bus_a ram=bus_write ram= 


s 


sp=dpl 




addr=fetch jump=true; 






pop? 


3_sp : 








// SP <= RAM[SP++], MPC <= # fetch 








sp=select_bus_a sp=register_load 








ram=select_bus_a ram=bus_write ram= 


s 


sp=dpl 




addr=fetch jump=true; 






pop<: 


3_c: 








// C <= RAM[SP++], MPC <= # fetch 








c=select_bus_a c=register_load 








ram=select_bus_a ram=bus_write ram= 


s 


sp=dpl 




addr=fetch jump=true; 






pop<: 


3_fl: 








// FL <= RAM[SP++], MPC <= # fetch 







692 



Version "D" 



f l=select_bus_a f l=register_load 




ram=select_bus_a ram=bus_write ram=s sp=dpl 




addr= fetch jump=true; 




pop8_mi : 




// TMP <= RAM[SP++] 




tmp=select_bus_a tmp=register_load 




ram=select_bus_a ram=bus_write ram=s sp=dpl; 




// RAM [I] <= TMP, MPC <= # fetch 




ram=select_bus_a ram=load ram=i 




tmp=select_bus_a tmp=bus_write 




addr=fetch jump=true; 




pop8_m j : 




// TMP <= RAM[SP++] 




tmp=select_bus_a tmp=register_load 




ram=select_bus_a ram=bus_write ram=s sp=dpl; 




// RAM [J] <= TMP, MPC <= # fetch 




ram=select_bus_a ram=load ram=j 




tmp=select_bus_a tmp=bus_write 




addr=fetch jump=true; 




jump : 




// TMP [7:0] <= RAM[PC++] 




tmp=select_bus_a tmp=rank_8 tmp=register_load_ 


_byte_l tmp=select_byte_l 


ram=select_bus_a ram=bus_write ram=p pc=dpl; 




// TMP [15: 8] <= RAM[PC++] 




tmp=select_bus_a tmp=rank_8 tmp=register_load_ 


_byte_2 tmp=select_byte_2 


ram=select_bus_a ram=bus_write ram=p pc=dpl; 




// PC <= TMP, MPC <= #fetch 




pc=select_bus_a pc=rank_16 pc=register_load 




tmp=select_bus_a tmp=rank_16 tmp=bus_write 




addr=fetch jump=true; 




jump_nc : 




addr=jump jump=carry_f ; 




// condition failed: ignore argument and jump 


to next instruction 


pc=qp2 pc=qup addr=fetch jump=true; 




j ump_c : 




addr=jump jump=carry_t ; 




// condition failed: ignore argument and jump 


to next instruction 


pc=qp2 pc=qup addr=fetch jump=true; 




jump_nz : 




addr=jump jump=zero_f; 




// condition failed: ignore argument and jump 


to next instruction 



Version "D" 



693 



pc=qp2 pc=qup addr=f etch jump=true; 










jump_z : 










addr=jump jump=zero_t ; 










// condition failed: ignore argument and 


jump 


to 


next 


instruction 


pc=qp2 pc=qup addr=fetch jump=true; 










jump_nn : 










addr=jump jump=negat ive_f ; 










// condition failed: ignore argument and 


jump 


to 


next 


instruction 


pc=qp2 pc=qup addr=fetch jump=true; 










j ump_n : 










addr=jump jump=negative_t ; 










// condition failed: ignore argument and 


jump 


to 


next 


instruction 


pc=qp2 pc=qup addr=fetch jump=true; 










jump_no : 










addr=jump jump=overf low_f ; 










// condition failed: ignore argument and 


jump 


to 


next 


instruction 


pc=qp2 pc=qup addr=fetch jump=true; 










j ump_o : 










addr=jump jump=overf low_t ; 










// condition failed: ignore argument and 


jump 


to 


next 


instruction 


pc=qp2 pc=qup addr=fetch jump=true; 










// 










equal : 










// C <= A (FL updated), MPC <= # fetch 










a=select_bus_a a=rank_16 a=bus_write 










c=select_bus_b c=rank_16 c=register_load 










f l=select_bus_b fl=rank_16 f l=register_load 








alu=a alu=rank_16 










addr=fetch jump=true; 










not : 










// C <= ~A (FL updated), MPC <= # fetch 










a=select_bus_a a=rank_16 a=bus_write 










c=select_bus_b c=rank_16 c=register_load 










f l=select_bus_b fl=rank_16 f l=register_load 








alu=not alu=rank_16 










addr=fetch jump=true; 










and : 










// C <= A&B (FL updated), MPC <= # fetch 










a=select_bus_a a=rank_16 a=bus_write 










b=select_bus_b b=rank_16 b=bus_write 










c=select_bus_b c=rank_16 c=register_load 











694 



Version "D" 



f l=select_bus_b fl=rank_16 f l=register_load 
alu=and alu=rank_16 
addr=fetch jump=true; 
nand : 

// C <= ~(A&B) (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
b=select_bus_b b=rank_16 b=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=nand alu=rank_16 
addr=fetch jump=true; 

or : 

// C <= A/B (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
b=select_bus_b b=rank_16 b=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=or alu=rank_16 
addr=fetch jump=true; 

nor : 

// C <= ~(AIB) (FL updated), MPC <= #fetch 

a=select_bus_a a=rank_16 a=bus_write 
b=select_bus_b b=rank_16 b=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=nor alu=rank_16 
addr=fetch jump=true; 

xor : 

// C <= A A B (FL updated) , MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
b=select_bus_b b=rank_16 b=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=xor alu=rank_16 
addr=fetch jump=true; 
nxor : 

// C <= ~(A*B) (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
b=select_bus_b b=rank_16 b=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 



Version "D" 



695 



alu=nxor alu=rank_16 
addr=f etch jump=true; 

add : 

// C <= A+B (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
b=select_bus_b b=rank_16 b=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=add alu=rank_16 
addr=fetch jump=true; 

sub : 

// C <= A-B (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
b=select_bus_b b=rank_16 b=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=sub alu=rank_16 
addr=fetch jump=true; 
addc : 

// C <= A+B+carry (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
b=select_bus_b b=rank_16 b=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=addc alu=rank_16 
addr=fetch jump=true; 
subb : 

// C <= A-B-borrow (FL updated) , MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
b=select_bus_b b=rank_16 b=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=subb alu=rank_16 
addr=fetch jump=true; 
lshl : 

// C <= lshl (A) (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=lshl alu=rank_16 
addr=fetch jump=true; 



696 



Version "D" 



lshr : 

// C <= lshr (A) (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=lshr alu=rank_16 
addr=fetch jump=true; 
ashl : 

// C <= ashl (A) (FL updated) , MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=ashl alu=rank_16 
addr=fetch jump=true; 
ashr : 

// C <= ashr (A) (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=ashr alu=rank_16 
addr=fetch jump=true; 
rotcl : 

// C <= rotcl (A) (FL updated) , MPC <= #fetch 

a=select_bus_a a=rank_16 a=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=rotcl alu=rank_16 
addr=fetch jump=true; 
rot cr : 

// C <= rotcr(A) (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=rotcr alu=rank_16 
addr=fetch jump=true; 
rotl : 

// C <= rotl (A) (FL updated) , MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=rotl alu=rank_16 



Version "D" 



697 



addr=f etch jump=true; 
rot r : 

// C <= rotr(A) (FL updated), MPC <= # fetch 

a=select_bus_a a=rank_16 a=bus_write 
c=select_bus_b c=rank_16 c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=rotr alu=rank_16 
addr=fetch jump=true; 
add8 : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 
b=select_bus_b b=bus_write 
c=select_bus_b c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=add alu=rank_8 
addr=fetch jump=true; 
sub8 : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 
b=select_bus_b b=bus_write 
c=select_bus_b c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=sub alu=rank_8 
addr=fetch jump=true; 
add8c : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 
b=select_bus_b b=bus_write 
c=select_bus_b c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=addc alu=rank_8 
addr=fetch jump=true; 
sub8b : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 
b=select_bus_b b=bus_write 
c=select_bus_b c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=subb alu=rank_8 
addr=fetch jump=true; 
lsh81 : 



698 



Version "D" 



// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 
c=select_bus_b c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=lshl alu=rank_8 
addr=fetch jump=true; 
lsh8r : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 
c=select_bus_b c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=lshr alu=rank_8 
addr=fetch jump=true; 
ash81 : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 
c=select_bus_b c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=ashl alu=rank_8 
addr=fetch jump=true; 
ash8r : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 
c=select_bus_b c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=ashr alu=rank_8 
addr=fetch jump=true; 
rot8cl : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 
c=select_bus_b c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=rotcl alu=rank_8 
addr=fetch jump=true; 
rot 8cr : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 

c=select_bus_b c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=rotcr alu=rank_8 

addr=fetch jump=true; 



Version "D" 



699 



rot81 : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 
c=select_bus_b c=register_load 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=rotl alu=rank_8 
addr=fetch jump=true; 
rot 8r : 

// C <= A[7:0]+B[7:0] (FL updated), MPC <= # fetch 

a=select_bus_a a=bus_write 

c=select_bus_b c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=rotr alu=rank_8 

addr=fetch jump=true; 

cast_uns_a : 

a=select_bus_a a=bus_write 

c=select_bus_b c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=a alu=rank_8; 

c=select_bus_a c=bus_write 

a=select_bus_a a=register_load 

addr=fetch jump=true; 
cast_uns_b : 

b=select_bus_a b=bus_write 

c=select_bus_b c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=a alu=rank_8; 

c=select_bus_a c=bus_write 

b=select_bus_a b=register_load 

addr=fetch jump=true; 
cast_sig_a : 

a=select_bus_a a=bus_write 

c=select_bus_b c=register_load c=rank_16 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=a alu=rank_8 alu=signed; 

c=select_bus_a c=bus_write c=rank_16 

a=select_bus_a a=register_load a=rank_16 

addr=fetch jump=true; 
cast_sig_b : 

b=select_bus_a b=bus_write 



700 



Version "D" 



c=select_bus_b c=register_load c=rank_16 












f l=select_bus_b fl=rank_16 f l=register_load 












alu=a alu=rank_8 alu=signed; 












c=select_bus_a c=bus_write c=rank_16 












b=select_bus_a b=register_load b=rank_16 












addr=fetch jump=true; 












equals : 












// A [7:0] <= RAM[SP] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


1 


a= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=s; 












// A[15:8] <= RAM[SP+1] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


2 


a= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 












// C <= A (FL updated), MPC <= # fetch 












a=select_bus_a a=rank_16 a=bus_write 












c=select_bus_b c=rank_16 c=register_load 












f l=select_bus_b fl=rank_16 f l=register_load 












alu=a alu=rank_16 












addr=fetch jump=true; 












not s : 












// A [7:0] <= RAM[SP] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


1 


a= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=s; 












// A[15:8] <= RAM[SP+1] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


2 


a= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 












// C <= ~A (FL updated) 












a=select_bus_a a=rank_16 a=bus_write 












c=select_bus_b c=rank_16 c=register_load 












f l=select_bus_b fl=rank_16 f l=register_load 












alu=not alu=rank_16; 












// RAM[SP] <= C[7:0] 












ram=select_bus_a ram=load ram=s 












c=select_bus_a c=rank_8 c=select_byte_l c=bus 


— 


write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 












ram=select_bus_a ram=load ram=s sp=qpl 












c=select_bus_a c=rank_8 c=select_byte_2 c=bus 


— 


write 






addr=fetch jump=true; 












ands : 












// B[7:0] <= RAM[SP] 












b=select_bus_a b=rank_8 b=register_load_byte_ 


1 


b= 


select. 


_byte_ 


,1 



Version "D" 



701 



ram=select_bus_a ram=bus_write ram=s; 












// B[15:8] <= RAM[SP+1] 












b=select_bus_a b=rank_8 b=register_load_byte_ 


2 


b= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 












// A[7:0] <= RAM[SP+2] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


1 


a= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=s sp=qp2; 












// A[15:8] <= RAM[SP+3] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


2 


a= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=s sp=qp3; 












// C <= A&B (FL updated) 












a=select_bus_a a=rank_16 a=bus_write 












b=select_bus_b b=rank_16 b=bus_write 












c=select_bus_b c=rank_16 c=register_load 












f l=select_bus_b fl=rank_16 f l=register_load 












alu=and alu=rank_16; 












// RAM[SP=SP+2] <= C[7:0] 












ram=select_bus_a ram=load ram=s sp=qp2 sp=qup 












c=select_bus_a c=rank_8 c=select_byte_l c=bus 




write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 












ram=select_bus_a ram=load ram=s sp=qpl 












c=select_bus_a c=rank_8 c=select_byte_2 c=bus 




write 






addr=fetch jump=true; 












nands : 












// B[7:0] <= RAM[SP] 












b=select_bus_a b=rank_8 b=register_load_byte_ 


1 


b= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=s; 












// B[15:8] <= RAM[SP+1] 












b=select_bus_a b=rank_8 b=register_load_byte_ 


2 


b= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 












// A [7:0] <= RAM[SP+2] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


1 


a= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=s sp=qp2; 












// A[15:8] <= RAM[SP+3] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


2 


a= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=s sp=qp3; 












// C <= ~(A&B) (FL updated) 












a=select_bus_a a=rank_16 a=bus_write 












b=select_bus_b b=rank_16 b=bus_write 












c=select_bus_b c=rank_16 c=register_load 












f l=select_bus_b fl=rank_16 f l=register_load 













702 



Version "D" 



alu=nand alu=rank_16; 








// RAM[SP=SP+2] <= C[7:0] 








ram=select_bus_a ram=load ram=s sp=qp2 sp=qup 








c=select_bus_a c=rank_8 c=select_byte_l c=bus_ 


write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus_ 


write 






addr=fetch jump=true; 








ors : 








// B[7:0] <= RAM[SP] 








b=select_bus_a b=rank_8 b=register_load_byte_l 


b=select_ 


_byte_ 


_1 


ram=select_bus_a ram=bus_write ram=s; 








// B[15:8] <= RAM[SP+1] 








b=select_bus_a b=rank_8 b=register_load_byte_2 


b=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 








// A [7:0] <= RAM[SP+2] 








a=select_bus_a a=rank_8 a=register_load_byte_l 


a=select_ 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=s sp=qp2; 








// A[15:8] <= RAM[SP+3] 








a=select_bus_a a=rank_8 a=register_load_byte_2 


a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qp3; 








// C <= A/B (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








b=select_bus_b b=rank_16 b=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=or alu=rank_16; 








// RAM[SP=SP+2] <= C[7:0] 








ram=select_bus_a ram=load ram=s sp=qp2 sp=qup 








c=select_bus_a c=rank_8 c=select_byte_l c=bus_ 


write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus_ 


write 






addr=fetch jump=true; 








nors : 








// B[7:0] <= RAM[SP] 








b=select_bus_a b=rank_8 b=register_load_byte_l 


b=select_ 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=s; 








// B[15:8] <= RAM[SP+1] 








b=select_bus_a b=rank_8 b=register_load_byte_2 


b=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 









Version "D" 



703 



// A[7:0] <= RAM[SP+2] 








a=select_bus_a a=rank_8 a=register_load_byte_l 


a=select_ 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=s sp=qp2; 








// A [15: 8] <= RAM[SP+3] 








a=select_bus_a a=rank_8 a=register_load_byte_2 


a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qp3; 








// C <= ~(AIB) (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








b=select_bus_b b=rank_16 b=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=nor alu=rank_16; 








// RAM[SP=SP+2] <= C[7:0] 








ram=select_bus_a ram=load ram=s sp=qp2 sp=qup 








c=select_bus_a c=rank_8 c=select_byte_l c=bus_ 


write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus_ 


write 






addr=fetch jump=true; 








xors : 








// B[7:0] <= RAM[SP] 








b=select_bus_a b=rank_8 b=register_load_byte_l 


b=select_ 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=s; 








// B[15:8] <= RAM[SP+1] 








b=select_bus_a b=rank_8 b=register_load_byte_2 


b=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 








// A [7:0] <= RAM[SP+2] 








a=select_bus_a a=rank_8 a=register_load_byte_l 


a=select_ 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=s sp=qp2; 








// A[15:8] <= RAM[SP+3] 








a=select_bus_a a=rank_8 a=register_load_byte_2 


a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qp3; 








// C <= A A B (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








b=select_bus_b b=rank_16 b=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=xor alu=rank_16; 








// RAM[SP=SP+2] <= C[7:0] 








ram=select_bus_a ram=load ram=s sp=qp2 sp=qup 








c=select_bus_a c=rank_8 c=select_byte_l c=bus_ 


write ; 







704 



Version "D" 



// RAM[SP+1] <= C[15:8], MPC <= iff etch 

ram=select_bus_a ram=load ram=s sp=qpl 
c=select_bus_a c=rank_8 c=select_byte_2 c=bus_write 
addr=fetch jump=true; 
nxors : 

// B[7:0] <= RAM[SP] 

b=select_bus_a b=rank_8 b=register_load_byte_l b=select_byte_l 
ram=select_bus_a ram=bus_write ram=s; 
// B[15:8] <= RAM[SP+1] 

b=select_bus_a b=rank_8 b=register_load_byte_2 b=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=qpl; 
// A [7:0] <= RAM[SP+2] 

a=select_bus_a a=rank_8 a=register_load_byte_l a=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=qp2; 
// A[15:8] <= RAM[SP+3] 

a=select_bus_a a=rank_8 a=register_load_byte_2 a=select_byte_2 

ram=select_bus_a ram=bus_write ram=s sp=qp3; 

// C <= ~(A*B) (FL updated) 

a=select_bus_a a=rank_16 a=bus_write 

b=select_bus_b b=rank_16 b=bus_write 

c=select_bus_b c=rank_16 c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=nxor alu=rank_16; 

// RAM[SP=SP+2] <= C[7:0] 

ram=select_bus_a ram=load ram=s sp=qp2 sp=qup 
c=select_bus_a c=rank_8 c=select_byte_l c=bus_write; 
// RAM[SP+1] <= C[15:8] , MPC <= # fetch 

ram=select_bus_a ram=load ram=s sp=qpl 
c=select_bus_a c=rank_8 c=select_byte_2 c=bus_write 
addr=fetch jump=true; 
adds : 

// B[7:0] <= RAM[SP] 

b=select_bus_a b=rank_8 b=register_load_byte_l b=select_byte_l 
ram=select_bus_a ram=bus_write ram=s; 
// B[15:8] <= RAM[SP+1] 

b=select_bus_a b=rank_8 b=register_load_byte_2 b=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=qpl; 
// A [7:0] <= RAM[SP+2] 

a=select_bus_a a=rank_8 a=register_load_byte_l a=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=qp2; 
// A[15:8] <= RAM[SP+3] 



Version "D" 



705 



a=select_bus_a a=rank_8 a=register_load_byte_2 


a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qp3; 








// C <= A+B (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








b=select_bus_b b=rank_16 b=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=add alu=rank_16; 








// RAM[SP=SP+2] <= C[7:0] 








ram=select_bus_a ram=load ram=s sp=qp2 sp=qup 








c=select_bus_a c=rank_8 c=select_byte_l c=bus_ 


write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus_ 


write 






addr=fetch jump=true; 








subs : 








// B[7:0] <= RAM[SP] 








b=select_bus_a b=rank_8 b=register_load_byte_l 


b=select_ 


_byte_ 


_1 


ram=select_bus_a ram=bus_write ram=s; 








// B[15:8] <= RAM[SP+1] 








b=select_bus_a b=rank_8 b=register_load_byte_2 


b=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 








// A [7:0] <= RAM[SP+2] 








a=select_bus_a a=rank_8 a=register_load_byte_l 


a=select_ 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=s sp=qp2; 








// A[15:8] <= RAM[SP+3] 








a=select_bus_a a=rank_8 a=register_load_byte_2 


a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qp3; 








// C <= A-B (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








b=select_bus_b b=rank_16 b=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=sub alu=rank_16; 








// RAM[SP=SP+2] <= C[7:0] 








ram=select_bus_a ram=load ram=s sp=qp2 sp=qup 








c=select_bus_a c=rank_8 c=select_byte_l c=bus_ 


write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus_ 


write 






addr=fetch jump=true; 









706 



Version "D" 



addcs : 

// B[7:0] <= RAM[SP] 

b=select_bus_a b=rank_8 b=register_load_byte_l b=select_byte_l 
ram=select_bus_a ram=bus_write ram=s; 
// B[15:8] <= RAM[SP+1] 

b=select_bus_a b=rank_8 b=register_load_byte_2 b=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=qpl; 
// A [7:0] <= RAM[SP+2] 

a=select_bus_a a=rank_8 a=register_load_byte_l a=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=qp2; 
// A[15:8] <= RAM[SP+3] 

a=select_bus_a a=rank_8 a=register_load_byte_2 a=select_byte_2 

ram=select_bus_a ram=bus_write ram=s sp=qp3; 

// C <= A+B+carry (FL updated) 

a=select_bus_a a=rank_16 a=bus_write 

b=select_bus_b b=rank_16 b=bus_write 

c=select_bus_b c=rank_16 c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=addc alu=rank_16; 

// RAM[SP=SP+2] <= C[7:0] 

ram=select_bus_a ram=load ram=s sp=qp2 sp=qup 
c=select_bus_a c=rank_8 c=select_byte_l c=bus_write; 
// RAM[SP+1] <= C[15:8], MPC <= # fetch 
ram=select_bus_a ram=load ram=s sp=qpl 
c=select_bus_a c=rank_8 c=select_byte_2 c=bus_write 
addr=fetch jump=true; 
subbs : 

// B[7:0] <= RAM[SP] 

b=select_bus_a b=rank_8 b=register_load_byte_l b=select_byte_l 
ram=select_bus_a ram=bus_write ram=s; 
// B[15:8] <= RAM[SP+1] 

b=select_bus_a b=rank_8 b=register_load_byte_2 b=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=qpl; 
// A [7:0] <= RAM[SP+2] 

a=select_bus_a a=rank_8 a=register_load_byte_l a=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=qp2; 
// A [15: 8] <= RAM[SP+3] 

a=select_bus_a a=rank_8 a=register_load_byte_2 a=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=qp3; 
// C <= A-B-borrow (FL updated) 

a=select bus a a=rank 16 a=bus write 



Version "D" 



707 



b=select_bus_b b=rank_16 b=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=subb alu=rank_16; 








// RAM[SP=SP+2] <= C[7:0] 








ram=select_bus_a ram=load ram=s sp=qp2 sp=qup 








c=select_bus_a c=rank_8 c=select_byte_l c=bus 


_write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus 


_write 






addr=fetch jump=true; 








lshls : 








// A [7:0] <= RAM[SP] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


1 a=select_ 


_byte_ 


_1 


ram=select_bus_a ram=bus_write ram=s; 








// A[15:8] <= RAM[SP+1] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


2 a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 








// C <= lshl (A) (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=lshl alu=rank_16; 








// RAM[SP] <= C[7:0] 








ram=select_bus_a ram=load ram=s 








c=select_bus_a c=rank_8 c=select_byte_l c=bus 


_write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus 


_write 






addr=fetch jump=true; 








lshrs : 








// A [7:0] <= RAM[SP] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


1 a=select_ 


_byte_ 


_1 


ram=select_bus_a ram=bus_write ram=s; 








// A[15:8] <= RAM[SP+1] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


2 a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 








// C <= lshr(A) (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 









708 



Version "D" 



alu=lshr alu=rank_16; 








// RAM[SP] <= C[7:0] 








ram=select_bus_a ram=load ram=s 








c=select_bus_a c=rank_8 c=select_byte_l c=bus 


_write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus 


_write 






addr=fetch jump=true; 








ashls : 








// A [7:0] <= RAM[SP] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


1 a=select_ 


_byte_ 


_1 


ram=select_bus_a ram=bus_write ram=s; 








// A[15:8] <= RAM[SP+1] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


2 a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 








// C <= ashl (A) (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=ashl alu=rank_16; 








// RAM[SP] <= C[7:0] 








ram=select_bus_a ram=load ram=s 








c=select_bus_a c=rank_8 c=select_byte_l c=bus 


_write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus 


_write 






addr=fetch jump=true; 








ashrs : 








// A [7:0] <= RAM[SP] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


1 a=select_ 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=s; 








// A[15:8] <= RAM[SP+1] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


2 a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 








// C <= ashr(A) (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=ashr alu=rank_16; 








// RAM[SP] <= C[7:0] 








ram=select_bus_a ram=load ram=s 









Version "D" 



709 



c=select_bus_a c=rank_8 c=select_byte_l c=bus_write; 
// RAM[SP+1] <= C[15:8], MPC <= # fetch 

ram=select_bus_a ram=load ram=s sp=qpl 
c=select_bus_a c=rank_8 c=select_byte_2 c=bus_write 
addr=fetch jump=true; 
rotcls : 

// A[7:0] <= RAM[SP] 

a=select_bus_a a=rank_8 a=register_load_byte_l a=select_byte_l 
ram=select_bus_a ram=bus_write ram=s; 
// A[15:8] <= RAM[SP+1] 

a=select_bus_a a=rank_8 a=register_load_byte_2 a=select_byte_2 

ram=select_bus_a ram=bus_write ram=s sp=qpl; 

// C <= rotcl (A) (FL updated) 

a=select_bus_a a=rank_16 a=bus_write 

c=select_bus_b c=rank_16 c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=rotcl alu=rank_16; 

// RAM[SP] <= C[7:0] 

ram=select_bus_a ram=load ram=s 

c=select_bus_a c=rank_8 c=select_byte_l c=bus_write; 
// RAM[SP+1] <= C[15:8] , MPC <= # fetch 

ram=select_bus_a ram=load ram=s sp=qpl 
c=select_bus_a c=rank_8 c=select_byte_2 c=bus_write 
addr=fetch jump=true; 
rot crs : 

// A [7:0] <= RAM[SP] 

a=select_bus_a a=rank_8 a=register_load_byte_l a=select_byte_l 
ram=select_bus_a ram=bus_write ram=s; 
// A[15:8] <= RAM[SP+1] 

a=select_bus_a a=rank_8 a=register_load_byte_2 a=select_byte_2 

ram=select_bus_a ram=bus_write ram=s sp=qpl; 

// C <= rotcr(A) (FL updated) 

a=select_bus_a a=rank_16 a=bus_write 

c=select_bus_b c=rank_16 c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=rotcr alu=rank_16; 

// RAM[SP] <= C[7:0] 

ram=select_bus_a ram=load ram=s 

c=select_bus_a c=rank_8 c=select_byte_l c=bus_write; 
// RAM[SP+1] <= C[15:8], MPC <= # fetch 

ram=select_bus_a ram=load ram=s sp=qpl 



710 



Version "D" 



c=select_bus_a c=rank_8 c=select_byte_2 c=bus 


_write 






addr=fetch jump=true; 








rot Is : 








// A [7:0] <= RAM[SP] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


1 a=select_ 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=s; 








// A[15:8] <= RAM[SP+1] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


2 a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 








// C <= rotl (A) (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=rotl alu=rank_16; 








// RAM[SP] <= C[7:0] 








ram=select_bus_a ram=load ram=s 








c=select_bus_a c=rank_8 c=select_byte_l c=bus 


_write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus 


_write 






addr=fetch jump=true; 








rotrs : 








// A [7:0] <= RAM[SP] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


1 a=select_ 


_byte_ 


1 


ram=select_bus_a ram=bus_write ram=s; 








// A[15:8] <= RAM[SP+1] 








a=select_bus_a a=rank_8 a=register_load_byte_ 


2 a=select_ 


_byte_ 


_2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 








// C <= rotr(A) (FL updated) 








a=select_bus_a a=rank_16 a=bus_write 








c=select_bus_b c=rank_16 c=register_load 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=rotr alu=rank_16; 








// RAM[SP] <= C[7:0] 








ram=select_bus_a ram=load ram=s 








c=select_bus_a c=rank_8 c=select_byte_l c=bus 


_write ; 






// RAM[SP+1] <= C[15:8], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qpl 








c=select_bus_a c=rank_8 c=select_byte_2 c=bus 


_write 






addr=fetch jump=true; 








add8s : 









Version "D" 



711 



// B <= RAM[SP] 

b=select_bus_a b=register_load 

ram=select_bus_a ram=bus_write ram=s; 

// A <= RAM[SP+1] 

a=select_bus_a a=register_load 

ram=select_bus_a ram=bus_write ram=s sp=qpl; 

// C <= A+B (FL updated) 

a=select_bus_a a=bus_write 

b=select_bus_b b=bus_write 

c=select_bus_b c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=add alu=rank_8; 

// RAM[SP=SP+1] <= C[7:0], MPC <= # fetch 

ram=select_bus_a ram=load ram=s sp=qpl sp=qup 
c=select_bus_a c=bus_write 
addr=fetch jump=true; 
sub8s : 

// B <= RAM[SP] 

b=select_bus_a b=register_load 

ram=select_bus_a ram=bus_write ram=s; 

// A <= RAM[SP+1] 

a=select_bus_a a=register_load 

ram=select_bus_a ram=bus_write ram=s sp=qpl; 

// C <= A-B (FL updated) 

a=select_bus_a a=bus_write 

b=select_bus_b b=bus_write 

c=select_bus_b c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=sub alu=rank_8; 

// RAM[SP=SP+1] <= C[7:0], MPC <= # fetch 

ram=select_bus_a ram=load ram=s sp=qpl sp=qup 
c=select_bus_a c=bus_write 
addr=fetch jump=true; 
add8cs : 

// B <= RAM[SP] 

b=select_bus_a b=register_load 
ram=select_bus_a ram=bus_write ram=s; 
// A <= RAM[SP+1] 
a=select_bus_a a=register_load 
ram=select_bus_a ram=bus_write ram=s sp=qpl; 
// C <= A+B+carry (FL updated) 



712 



Version "D" 



a=select_bus_a a=bus_write 

b=select_bus_b b=bus_write 

c=select_bus_b c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=addc alu=rank_8; 

// RAM[SP=SP+1] <= C[7:0], MPC <= # fetch 

ram=select_bus_a ram=load ram=s sp=qpl sp=qup 
c=select_bus_a c=bus_write 
addr=fetch jump=true; 
sub8bs : 

// B <= RAM[SP] 

b=select_bus_a b=register_load 

ram=select_bus_a ram=bus_write ram=s; 

// A <= RAM[SP+1] 

a=select_bus_a a=register_load 

ram=select_bus_a ram=bus_write ram=s sp=qpl; 

// C <= A-B-borrow (FL updated) 

a=select_bus_a a=bus_write 

b=select_bus_b b=bus_write 

c=select_bus_b c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=subb alu=rank_8; 

// RAM[SP=SP+1] <= C[7:0], MPC <= # fetch 

ram=select_bus_a ram=load ram=s sp=qpl sp=qup 
c=select_bus_a c=bus_write 
addr=fetch jump=true; 
lsh81s : 

// A <= RAM[SP] 

a=select_bus_a a=register_load 
ram=select_bus_a ram=bus_write ram=s; 
// C <= lsh81 (A) (FL updated) 

a=select_bus_a a=bus_write 

c=select_bus_b c=register_load 

f l=select_bus_b fl=rank_16 f l=register_load 

alu=lshl alu=rank_8; 

// RAM[SP] <= C[1:0], MPC <= # fetch 

ram=select_bus_a ram=load ram=s 
c=select_bus_a c=bus_write 
addr=fetch jump=true; 
lsh8rs : 

// A <= RAM[SP] 



Version "D" 



713 



a=select_bus_a a=register_load 




ram=select_bus_a ram=bus_write ram=s; 




// C <= lsh8r(A) (FL updated) 




a=select_bus_a a=bus_write 




c=select_bus_b c=register_load 




f l=select_bus_b fl=rank_16 fl=register_ 


_load 


alu=lshr alu=rank_8; 




// RAM[SP] <= C[7:0], MPC <= # fetch 




ram=select_bus_a ram=load ram=s 




c=select_bus_a c=bus_write 




addr=fetch jump=true; 




ash81s : 




// A <= RAM[SP] 




a=select_bus_a a=register_load 




ram=select_bus_a ram=bus_write ram=s; 




// C <= ash81 (A) (FL updated) 




a=select_bus_a a=bus_write 




c=select_bus_b c=register_load 




f l=select_bus_b fl=rank_16 fl=register_ 


_load 


alu=ashl alu=rank_8; 




// RAM[SP] <= C[1:0], MPC <= # fetch 




ram=select_bus_a ram=load ram=s 




c=select_bus_a c=bus_write 




addr=fetch jump=true; 




ash8rs : 




// A <= RAM[SP] 




a=select_bus_a a=register_load 




ram=select_bus_a ram=bus_write ram=s; 




// C <= ash8r(A) (FL updated) 




a=select_bus_a a=bus_write 




c=select_bus_b c=register_load 




f l=select_bus_b fl=rank_16 fl=register_ 


_load 


alu=ashr alu=rank_8; 




// RAM[SP] <= C[1:0], MPC <= # fetch 




ram=select_bus_a ram=load ram=s 




c=select_bus_a c=bus_write 




addr=fetch jump=true; 




rot 8cls : 




// A <= RAM[SP] 




a=select_bus_a a=register_load 




ram=select_bus_a ram=bus_write ram=s; 





714 



Version "D" 



// C <= rot8cl (A) (FL updated) 




a=select_bus_a a=bus_write 




c=select_bus_b c=register_load 




f l=select_bus_b fl=rank_16 fl=register_ 


_load 


alu=rotcl alu=rank_8; 




// RAM[SP] <= C[1:0], MPC <= # fetch 




ram=select_bus_a ram=load ram=s 




c=select_bus_a c=bus_write 




addr=fetch jump=true; 




rot 8crs : 




// A <= RAM[SP] 




a=select_bus_a a=register_load 




ram=select_bus_a ram=bus_write ram=s; 




// C <= rot8cr(A) (FL updated) 




a=select_bus_a a=bus_write 




c=select_bus_b c=register_load 




f l=select_bus_b fl=rank_16 fl=register_ 


_load 


alu=rotcr alu=rank_8; 




// RAM[SP] <= C[1:0], MPC <= # fetch 




ram=select_bus_a ram=load ram=s 




c=select_bus_a c=bus_write 




addr=fetch jump=true; 




rot81s : 




// A <= RAM[SP] 




a=select_bus_a a=register_load 




ram=select_bus_a ram=bus_write ram=s; 




// C <= rot81 (A) (FL updated) 




a=select_bus_a a=bus_write 




c=select_bus_b c=register_load 




f l=select_bus_b fl=rank_16 fl=register_ 


_load 


alu=rotl alu=rank_8; 




// RAM[SP] <= C[7:0], MPC <= # fetch 




ram=select_bus_a ram=load ram=s 




c=select_bus_a c=bus_write 




addr=fetch jump=true; 




rot 8rs : 




// A <= RAM[SP] 




a=select_bus_a a=register_load 




ram=select_bus_a ram=bus_write ram=s; 




// C <= rot 8 r (A) (FL updated) 




a=select_bus_a a=bus_write 





Version "D" 



715 



c=select_bus_b c=register_load 




f l=select_bus_b fl=rank_16 f l=register_load 




alu=rotr alu=rank_8; 




// RAM[SP] <= C[1:0], MPC <= # fetch 




ram=select_bus_a ram=load ram=s 




c=select_bus_a c=bus_write 




addr=fetch jump=true; 




casts_uns : 




// A <= RAM[SP] 




a=select_bus_a a=register_load 




ram=select_bus_a ram=bus_write ram=s; 




// C <= A[7:0] (FL updated) 




a=select_bus_a a=bus_write 




c=select_bus_b c=register_load c=rank_16 




f l=select_bus_b fl=rank_16 f l=register_load 




alu=a alu=rank_8; 




// RAM[SP] <= C[7:0] 




ram=select_bus_a ram=load ram=s 




c=select_bus_a c=rank_8 c=select_byte_l c=bus_ 


_write ; 


// RAM[SP+1] <= C[15:8], MPC <= # fetch 




ram=select_bus_a ram=load ram=s sp=qpl 




c=select_bus_a c=rank_8 c=select_byte_2 c=bus_ 


_write 


addr=fetch jump=true; 




casts_sig : 




// A <= RAM[SP] 




a=select_bus_a a=register_load 




ram=select_bus_a ram=bus_write ram=s; 




// C <= A[7:0] (FL updated) 




a=select_bus_a a=bus_write 




c=select_bus_b c=register_load c=rank_16 




f l=select_bus_b fl=rank_16 f l=register_load 




alu=a alu=rank_8 alu=signed; 




// RAM[SP] <= C[7:0] 




ram=select_bus_a ram=load ram=s 




c=select_bus_a c=rank_8 c=select_byte_l c=bus_ 


_write ; 


// RAM[SP+1] <= C[15:8] , MPC <= # fetch 




ram=select_bus_a ram=load ram=s sp=qpl 




c=select_bus_a c=rank_8 c=select_byte_2 c=bus_ 


_write 


addr=fetch jump=true; 




call : 




// TMP[7:0] <= RAM[PC++] 





716 



Version "D" 



tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_l tmp=select_byte_l 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 
// TMP[15:8] <= RAM[PC++] 

tmp=select_bus_a tmp=rank_8 tmp=register_load_byte_2 tmp=select_byte_2 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 
// RAM[ — SP] <= PC [15: 8] 

ram=select_bus_a ram=load ram=s sp=qml sp=qup 
pc=select_bus_a pc=rank_8 pc=select_byte_2 pc=bus_write; 
// RAM[ — SP] <= PC[7:0], MPC <= # fetch 
ram=select_bus_a ram=load ram=s sp=qml sp=qup 
pc=select_bus_a pc=rank_8 pc=select_byte_l pc=bus_write; 
// PC <= TUP, MPC <= #fetch 

pc=select_bus_a pc=rank_16 pc=register_load 
tmp=select_bus_a tmp=rank_16 tmp=bus_write 
addr=fetch jump=true; 
call_i : 

// RAM[ — SP] <= PC [15: 8] 

ram=select_bus_a ram=load ram=s sp=qml sp=qup 
pc=select_bus_a pc=rank_8 pc=select_byte_2 pc=bus_write; 
// RAM[ — SP] <= PC[1:0], MPC <= # fetch 
ram=select_bus_a ram=load ram=s sp=qml sp=qup 
pc=select_bus_a pc=rank_8 pc=select_byte_l pc=bus_write; 
// PC <= I, MPC <= # fetch 

pc=select_bus_a pc=rank_16 pc=register_load 
i=select_bus_a i=rank_16 i=bus_write 
addr=fetch jump=true; 
call_j : 

// RAM[ — SP] <= PC [15: 8] 

ram=select_bus_a ram=load ram=s sp=qml sp=qup 
pc=select_bus_a pc=rank_8 pc=select_byte_2 pc=bus_write; 
// RAM[ — SP] <= PC[7:0], MPC <= # fetch 
ram=select_bus_a ram=load ram=s sp=qml sp=qup 
pc=select_bus_a pc=rank_8 pc=select_byte_l pc=bus_write; 
// PC <= J, MPC <= # fetch 

pc=select_bus_a pc=rank_16 pc=register_load 
j=select_bus_a j=rank_16 j=bus_write 
addr=fetch jump=true; 
return : 

// PC [7:0] <= RAM[SP++] 

pc=select_bus_a pc=rank_8 pc=register_load_byte_l pc=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=dpl; 



Version "D" 



717 



// PC [15: 8] <= RAM[SP++] , MPC <= # fetch 








pc=select_bus_a pc=rank_8 pc=register_load_byte_2 


pc=select 


_byte 


_2 


ram=select_bus_a ram=bus_write ram=s sp=dpl 








addr=fetch jump=true; 








ivtl : 








// TMP[7:0] <= RAM[PC++] 








tmp=select_bus_a tmp=rank_8 tmp=register_load_byte 


_1 tmp=select_ 


byte_l 


ram=select_bus_a ram=bus_write ram=p pc=dpl; 








// TMP[15:8] <= RAM[PC++] 








tmp=select_bus_a tmp=rank_8 tmp=register_load_byte 


_2 tmp=select_ 


byte_2 


ram=select_bus_a ram=bus_write ram=p pc=dpl; 








// IVT <= TMP , MPC <= # fetch 








ivt=ivt_load 








tmp=select_bus_a tmp=rank_16 tmp=bus_write 








addr=fetch jump=true; 








int : 








// 








// push FL 








// 








// RAM[ — SP] <= FL[15:8] 








ram=select_bus_a ram=load ram=s sp=qml sp=qup 








f l=select_bus_a fl=rank_8 f l=select_byte_2 fl=bus_ 


write ; 






// RAM[ — SP] <= FL[7:0], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qml sp=qup 








f l=select_bus_a fl=rank_8 f l=select_byte_l fl=bus_ 


write ; 






// 








// Reset interrupt enable flag 








// 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=cleari ; 








// 








// push (PC+1) to jump over the interrupt argument 








// 








//RAM[ — SP] <= (PC+1) [15:8] 








ram=select_bus_a ram=load ram=s sp=qml sp=qup 








pc=select_bus_a pc=rank_8 pc=select_byte_2 pc=bus_ 


write pc= 


qpl; 




// RAM[ — SP] <= (PC+1) [7:0] 








ram=select_bus_a ram=load ram=s sp=qml sp=qup 








pc=select_bus_a pc=rank_8 pc=select_byte_l pc=bus_ 


write pc= 


qpl; 




// 








// Convert the interrupt number from the argument, 


to the 







718 



Version "D" 



// interrupt vector table item address: 












// TMP <= IVT[int], int <= RAM [PC] 












// 












// TMP <= IVT[RAM[PC] ] 












tmp=select_bus_a tmp=rank_16 tmp=register_load 












ivt=select_int_b ivt=bus_write 












ram=select_bus_b ram=bus_write ram=p; 












// 












// Prepare to call the interrupt routine, loading the 






// interrupt vector table item address into PC. 












// 












// PC [7:0] <= RAM [TMP] 












pc=select_bus_a pc=rank_8 pc=register_load_byte_ 


1 


pc= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=t ; 












// PC [15: 8] <= RAM[TMP+1 ] , MPC <= # fetch 












pc=select_bus_a pc=rank_8 pc=register_load_byte_ 


_2 


pc= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=t tmp=qpl 












addr=fetch jump=true; 












iret : 












// 












// Pop PC 












// 












// PC [7:0] <= RAM[SP++] 












pc=select_bus_a pc=rank_8 pc=register_load_byte_ 


1 


pc= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=s sp=dpl; 












// PC [15: 8] <= RAM[SP++] 












pc=select_bus_a pc=rank_8 pc=register_load_byte_ 


_2 


pc= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=s sp=dpl; 












// 












// Pop FL 












// 












// FL[7:0] <= RAM[SP++] 












f l=select_bus_a fl=rank_8 f l=register_load_byte_ 


1 


f 1= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=s sp=dpl; 












// FL[15:8] <= RAM[SP++] , MPC <= # fetch 












f l=select_bus_a fl=rank_8 f l=register_load_byte_ 


_2 


f 1= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=s sp=dpl 












addr=fetch jump=true; 












imrl : 












// IRQ <= RAM[PC++] , MPC <= # fetch 












irq=irq_mask_load 













Version "D" 



719 



ram=select_bus_a ram=bus_write ram=p pc=dpl 






addr=fetch jump=true; 






irq : 






// 






// push FL 






// 






// RAM[ — SP] <= FL[15:8] 






ram=select_bus_a ram=load ram=s sp=qml sp=qup 






f l=select_bus_a fl=rank_8 f l=select_byte_2 f l=bus_write; 






// RAM[ — SP] <= FL[7:0], MPC <= # fetch 






ram=select_bus_a ram=load ram=s sp=qml sp=qup 






f l=select_bus_a fl=rank_8 f l=select_byte_l f l=bus_write; 






// 






// Reset interrupt enable flag 






// 






f l=select_bus_b fl=rank_16 f l=register_load 






alu=cleari ; 






// 






// push (PC-1) to jump back to the opcode just read. 






// 






//RAMI — SP] <= (PC-1) [15:8] 






ram=select_bus_a ram=load ram=s sp=qml sp=qup 






pc=select_bus_a pc=rank_8 pc=select_byte_2 pc=bus_write 


pc= 


qml; 


// RAM[ — SP] <= (PC-1) [7:0] 






ram=select_bus_a ram=load ram=s sp=qml sp=qup 






pc=select_bus_a pc=rank_8 pc=select_byte_l pc=bus_write 


pc= 


qml; 


// 






// Convert the interrupt number from the IRQ module, to 


the 


// interrupt vector table item address: 






// TMP <= IVT[int], int <= IRQ 






// 






// TMP <= IVT[INT[IRQ] ] 






tmp=select_bus_a tmp=rank_16 tmp=register_load 






ivt=select_int_a ivt=bus_write; 






// 






// Prepare to call the interrupt routine, loading the 






// interrupt vector table item address into PC. 






// 






// PC [7:0] <= RAM [TMP] 






pc=select_bus_a pc=rank_8 pc=register_load_byte_l pc=select 


_byte_l 


ram=select_bus_a ram=bus_write ram=t ; 







720 



Version "D" 



// PC [15: 8] <= RAM[TMP+1] 








pc=select_bus_a pc=rank_8 pc=register_load_byte_2 


pc=select 


_byte_2 


ram=select_bus_a ram=bus_write ram=t tmp=qpl; 








// 








// Set the IRQ received as already done, 








// MPC <= # fetch 








irq=irq_done 








addr=f etch jump=true; 








op_error : 








// 








// push FL 








// 








// RAM[ — SP] <= FL[15:8] 








ram=select_bus_a ram=load ram=s sp=qml sp=qup 








f l=select_bus_a fl=rank_8 f l=select_byte_2 fl=bus_ 


_write ; 






// RAM[ — SP] <= FL[7:0], MPC <= # fetch 








ram=select_bus_a ram=load ram=s sp=qml sp=qup 








f l=select_bus_a fl=rank_8 f l=select_byte_l fl=bus_ 


_write ; 






// 








// Reset interrupt enable flag 








// 








f l=select_bus_b fl=rank_16 f l=register_load 








alu=cleari ; 








// 








// push (PC-1) to jump back to the opcode just read. 






// 








//RAMI — SP] <= (PC-1) [15:8] 








ram=select_bus_a ram=load ram=s sp=qml sp=qup 








pc=select_bus_a pc=rank_8 pc=select_byte_2 pc=bus_ 


_write 


pc= 


qml; 


// RAM[—SP] <= (PC-1) [7:0] 








ram=select_bus_a ram=load ram=s sp=qml sp=qup 








pc=select_bus_a pc=rank_8 pc=select_byte_l pc=bus_ 


_write 


pc= 


qml ; 


// 








// Convert the interrupt number 0 to the 








// interrupt vector table item address: 








// 








// TMP <= IVT[0] 








tmp=select_bus_a tmp=rank_16 tmp=register_load 








ivt=select_int_b ivt=bus_write 








bus=bw bus=select_bus_b bus=0; 








// 









Version "D" 



721 



// Prepare to call the interrupt routine, loading the 




// interrupt vector table 


item address into PC. 








// 










// PC [7:0] <= RAM [TMP] 










pc=select_bus_a pc=rank_8 


pc=register_load_byte_ 


1 


pc=select_ 


_byte_l 


ram=select_bus_a ram=bus_write ram=t ; 








// PC [15: 8] <= RAM[TMP+1] , 


MPC <= # fetch 








pc=select_bus_a pc=rank_8 


pc=register_load_byte_ 


_2 


pc=select_ 


_byte_2 


ram=select_bus_a ram=bus_write ram=t tmp=qpl 








addr=fetch jump=true; 










f lag_i_clr : 










// FL <= FL&OxFFEF, MPC <= 


# fetch 








f l=select_bus_b fl=rank_16 


f l=register_load 








alu=cleari irq=irq_done 










addr=fetch jump=true; 










f lag_i_set : 










// FL <= FL 10x0010, MPC <= 


# fetch 








f l=select_bus_b fl=rank_16 


f l=register_load 








alu=seti irq=irq_done 










addr=fetch jump=true; 










f lag_c_clr : 










// FL <= FL&OxFFFE, MPC <= 


# fetch 








f l=select_bus_b fl=rank_16 


f l=register_load 








alu=clearc 










addr=fetch jump=true; 










f lag_c_set : 










// FL <= FL&OxOOOl, MPC <= 


# fetch 








f l=select_bus_b fl=rank_16 


f l=register_load 








alu=setc 










addr=fetch jump=true; 










i n_num_a : 










// IOA <= RAM[PC++] 










ioa=select_bus_a ioa=register_load 








ram=select_bus_a ram=bus_write ram=p pc=dpl; 








// I/O request 










ioc=req; 










// Time to wait . 










ctrl=nop; 










// A <= IOC, MPC <= # fetch 










a=select_bus_a a=register_ 


load ioc=bus_write 








addr=fetch jump=true; 











722 



Version "D" 



i n_num_b : 

// IOA <= RAM[PC++] 

ioa=select_bus_a ioa=register_load 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 
// I/O request 
ioc=req; 

// Time to wait . 

ctrl=nop; 

// B <= IOC, MPC <= # fetch 

b=select_bus_a b=register_load ioc=bus_write 
addr=fetch jump=true; 
in_num_mi : 

// IOA <= RAM[PC++] 
ioa=select_bus_a ioa=register_load 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 
// I/O request 
ioc=req; 

// Time to wait . 

ctrl=nop; 

// RAM [I] <= IOC, MPC <= # fetch 

ram=select_bus_a ram=load ram=i ioc=bus_write 
addr=fetch jump=true; 
in_num_m j : 

// IOA <= RAM[PC++] 
ioa=select_bus_a ioa=register_load 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 
// I/O request 
ioc=req; 

// Time to wait . 

ctrl=nop; 

// RAM [J] <= IOC, MPC <= # fetch 

ram=select_bus_a ram=load ram=j ioc=bus_write 
addr=fetch jump=true; 
out_a_num : 

// IOA <= RAM[PC++] 
ioa=select_bus_a ioa=register_load 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 
// IOC <= A 

ioc=load a=select_bus_a a=bus_write; 
// I/O request, MPC <= #fetch 

ioc=req 



Version "D" 



723 





addr=fetch jump=true; 




out_ 


_b_num : 






// IOA <= RAM[PC++] 






ioa=select_bus_a ioa=register_load 






ram=select_bus_a ram=bus_write ram=p pc=dpl; 






// IOC <= B 






ioc=load b=select_bus_a b=bus_write; 






// I/O request, MPC <= #fetch 






ioc=req 






addr=fetch jump=true; 




out_ 


_mi_num : 






// IOA <= RAM[PC++] 






ioa=select_bus_a ioa=register_load 






ram=select_bus_a ram=bus_write ram=p pc=dpl; 






// IOC <= RAM[I] 






ioc=load ram=select_bus_a ram=bus_write ram= 


i; 




// I/O request, MPC <= #fetch 






ioc=req 






addr=fetch jump=true; 




out_ 


_m j_num : 






// IOA <= RAM[PC++] 






ioa=select_bus_a ioa=register_load 






ram=select_bus_a ram=bus_write ram=p pc=dpl; 






// IOC <= RAM[J] 






ioc=load ram=select_bus_a ram=bus_write ram= 


j; 




// I/O request, MPC <= #fetch 






ioc=req 






addr=fetch jump=true; 




if ack_ jump : 






// IOA <= RAM[PC++] 






ioa=select_bus_a ioa=register_load 






ram=select_bus_a ram=bus_write ram=p pc=dpl; 






// C <= alu(I/0 isack) (FL updated), if ack 


MPC <= #jump 




ioc=isack ioc=bus_write 






c=select_bus_b c=register_load c=rank_16 






f l=select_bus_b fl=rank_16 f l=register_load 






alu=a alu=rank_8 alu=signed 






addr=jump jump=zero_f ; 






// discard argument and load next opcode 






pc=qp2 pc=qup addr=fetch jump=true; 




if ack call : 











724 



Version "D" 



// IOA <= RAM[PC++] 

ioa=select_bus_a ioa=register_load 
ram=select_bus_a ram=bus_write ram=p pc=dpl; 

// C <= alu (I/O isack) (FL updated), if ack MPC <= #ifack_call_ok 

ioc=isack ioc=bus_write 

c=select_bus_b c=register_load c=rank_16 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=a alu=rank_8 alu=signed 
addr=call jump=zero_f; 

// discard argument and load next opcode 

pc=qp2 pc=qup addr=fetch jump=true; 
cmpr : 

// FL(A-B), MPC <= # fetch 

a=select_bus_a a=bus_write a=rank_16 
b=select_bus_b b=bus_write b=rank_16 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=sub alu=rank_16 
addr=fetch jump=true; 
testr : 

// FL (A&B) , MPC <= # fetch 

a=select_bus_a a=bus_write a=rank_16 
b=select_bus_b b=bus_write b=rank_16 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=and alu=rank_16 
addr=fetch jump=true; 
cmpi : 

// A [7:0] <= RAM [I] 

a=select_bus_a a=rank_8 a=register_load_byte_l a=select_byte_l 
ram=select_bus_a ram=bus_write ram=i; 
// A [15: 8] <= RAM[I+1], MPC <= # fetch 

a=select_bus_a a=rank_8 a=register_load_byte_2 a=select_byte_2 
ram=select_bus_a ram=bus_write ram=i i=qpl 
// B[7:0] <= RAM [J] 

b=select_bus_a b=rank_8 b=register_load_byte_l b=select_byte_l 
ram=select_bus_a ram=bus_write ram=j; 
// B[15:8] <= RAM[J+1] , MPC <= # fetch 

b=select_bus_a b=rank_8 b=register_load_byte_2 b=select_byte_2 
ram=select_bus_a ram=bus_write ram=j j=qpl; 
// FL(A-B), MPC <= # fetch 

a=select_bus_a a=bus_write a=rank_16 
b=select bus b b=bus write b=rank 16 



Version "D" 



725 



f l=select_bus_b fl=rank_16 f l=register_load 












alu=sub alu=rank_16 












addr=fetch jump=true; 












testi : 












// A [7:0] <= RAM [I] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


1 


a= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=i; 












// A[15:8] <= RAM[I+1], MPC <= # fetch 












a=select_bus_a a=rank_8 a=register_load_byte_ 


_2 


a= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=i i=qpl 












// B[7:0] <= RAM [J] 












b=select_bus_a b=rank_8 b=register_load_byte_ 


1 


b= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=j; 












// B[15:8] <= RAM[J+1] , MPC <= # fetch 












b=select_bus_a b=rank_8 b=register_load_byte_ 


_2 


b= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=j j=qpl; 












// FL (A&B) , MPC <= # fetch 












a=select_bus_a a=bus_write a=rank_16 












b=select_bus_b b=bus_write b=rank_16 












f l=select_bus_b fl=rank_16 f l=register_load 












alu=and alu=rank_16 












addr=fetch jump=true; 












cmps : 












// B[7:0] <= RAM[SP] 












b=select_bus_a b=rank_8 b=register_load_byte_ 


1 


b= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=s; 












// B[15:8] <= RAM[SP+1] 












b=select_bus_a b=rank_8 b=register_load_byte_ 


_2 


b= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=s sp=qpl; 












// A [7:0] <= RAM[SP+2] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


1 


a= 


select. 


_byte_ 


,1 


ram=select_bus_a ram=bus_write ram=s sp=qp2; 












// A [15: 8] <= RAM[SP+3] 












a=select_bus_a a=rank_8 a=register_load_byte_ 


_2 


a= 


select. 


_byte_ 


,2 


ram=select_bus_a ram=bus_write ram=s sp=qp3; 












// FL(A-B), MPC <= # fetch 












a=select_bus_a a=bus_write a=rank_16 












b=select_bus_b b=bus_write b=rank_16 












f l=select_bus_b fl=rank_16 f l=register_load 












alu=sub alu=rank_16 












addr=fetch jump=true; 













726 



Version "D" 



tests : 

// B[7:0] <= RAM[SP] 

b=select_bus_a b=rank_8 b=register_load_byte_l b=select_byte_l 
ram=select_bus_a ram=bus_write ram=s; 
// B[15:8] <= RAM[SP+1] 

b=select_bus_a b=rank_8 b=register_load_byte_2 b=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=qpl; 
// A [7:0] <= RAM[SP+2] 

a=select_bus_a a=rank_8 a=register_load_byte_l a=select_byte_l 
ram=select_bus_a ram=bus_write ram=s sp=qp2; 
// A[15:8] <= RAM[SP+3] 

a=select_bus_a a=rank_8 a=register_load_byte_2 a=select_byte_2 
ram=select_bus_a ram=bus_write ram=s sp=qp3; 
// FL (A&B) , MPC <= # fetch 
a=select_bus_a a=bus_write a=rank_16 
b=select_bus_b b=bus_write b=rank_16 
f l=select_bus_b fl=rank_16 f l=register_load 
alu=and alu=rank_16 
addr=fetch jump=true; 
cmp8i : 

// A <= RAM [I] 

a=select_bus_a a=register_load 
ram=select_bus_a ram=bus_write ram=i; 
// B <= RAM [J] 

b=select_bus_a b=register_load 
ram=select_bus_a ram=bus_write ram=j; 
// FL(A-B), MPC <= # fetch 

a=select_bus_a a=bus_write 
b=select_bus_b b=bus_write 

f l=select_bus_b fl=rank_16 f l=register_load 
alu=sub alu=rank_8 
addr=fetch jump=true; 
test8i : 

// A <= RAM [I] 

a=select_bus_a a=register_load 
ram=select_bus_a ram=bus_write ram=i; 
// B <= RAM [J] 

b=select_bus_a b=register_load 
ram=select_bus_a ram=bus_write ram=j; 
// FL (A&B) , MPC <= # fetch 

a=select_bus_a a=bus_write 



Version "D" 



727 



b=select_bus_b b=bus_write 

f l=select_bus_b fl=rank_16 f l=register_load 
alu=and alu=rank_8 
addr=fetch jump=true; 
cmp8s : 

// B <= RAM[SP] 

b=select_bus_a b=register_load 
ram=select_bus_a ram=bus_write ram=s; 
// A <= RAM[SP+1] 
a=select_bus_a a=register_load 
ram=select_bus_a ram=bus_write ram=s sp=qpl; 
// FL(A-B), MPC <= # fetch 
a=select_bus_a a=bus_write 
b=select_bus_b b=bus_write 

f l=select_bus_b fl=rank_16 f l=register_load 
alu=sub alu=rank_8 
addr=fetch jump=true; 
test8s : 

// B <= RAM[SP] 

b=select_bus_a b=register_load 
ram=select_bus_a ram=bus_write ram=s; 
// A <= RAM[SP+1] 
a=select_bus_a a=register_load 
ram=select_bus_a ram=bus_write ram=s sp=qpl; 
// FL (A&B) , MPC <= # fetch 
a=select_bus_a a=bus_write 
b=select_bus_b b=bus_write 

f l=select_bus_b fl=rank_16 f l=register_load 
alu=and alu=rank_8 
addr=fetch jump=true; 
stop : 

ctrl=stop; 

addr=fetch jump=true; 

// 

end 



728 



Version "D 



11.16 Macrocode 



« 



As an example, the following listing shows a simple program that reads from the 
keyboard and prints the same text on the virtual screen. The keyboard input is read 
after a hardware interrupt. 

Listing 11.44. Macrocode example for TKGate. 

begin macrocode @ 0 



. short 


0x0025 


// 


CPU opcode error 


. short 


0x0024 


// 


CPU 


. short 


0x0024 


// 


CPU 


. short 


0x0024 


// 


CPU 


. short 


0x0024 


// 


IRQ rtc 


. short 


0x0026 


// 


IRQ keyboard 


. short 


0x0024 


// 


IRQ hard disk 


. short 


0x0024 


// 


IRQ 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 



clef ault_interrupt_rout ine : 

iret 
op_code_error : 

stop 
keyboard : 



jump # start 
nop 

interrupt_vect or_t able 



in 1,%A 
equal 

jump %zero, 1 , #keyboard_end 

out %A, 0 

jump #keyboard 



// keyboard read 
// update flags 
// if zero exit 



// print on screen 
// continue 



keyboard_end : 



Version "D" 



729 





iret 








start : 












cp UXUUoU, -s± 






SeC SZ.2LCK OOZ.Z.OIU 




Cp '51/ -5 or 










// 










lvti f interrupt vecior_ 


_L dDie 








/ / 
// 
















an ircy accepveo. 




flag_i 1 




// 


Xi<y enabled 


// 










keyboard_reset : 










in 1,%A 




// 


keyboard read . 




equal 




// 


upaatc i layo 




jump %zero, 0 , #keyboard_ 


.reset 


// 


if not zero continue 


// 










loop : 


jump #loop 








stop : 


// never 


reach 


the end. 




stop 








end 











730 Version "D" 



731 

Version "E" 



Chapter 1 



12.1 General purpose modules 734 

12.2 Module "MEM" 739 

12.2. 1 Module "MAR" 740 

12.2.2 Module "MIR" 742 

12.2.3 Module "MDR" 743 

12.3 General purpose registers 744 

12.4 Module "ALU" and related submodules 748 

12.5 Module "BUS" 755 

12.6 Module "IRQ" 756 

12.7 Module "IVT" 757 

12.8 Module "RTC": real time clock 758 

12.9 Module "TTY" 759 

12.10 Module "HDD" 763 

12.11 Module "CTRL" 768 

12.11.1 Modules "Fw" 769 

12. 1 1 .2 Module "CLK_CLR" 770 

12.12 Memory and microcode fields 772 

12.13 Opcodes 776 

12.14 Microcode 806 

12.15 Macrocode 845 



This version of the project is made to resolve the memory access problem previously 
evidenced. There is a module MEM that includes an MAR register for the address, the 
MIR register {memory instruction register, ex IR) and a renewed MDR register. To 



732 



Version "E" 



access the memory, it is required to put the address inside the MAR register, specify- 
ing the rank and the direction (read or write); then the read or write starts and stops 
automatically. But this process requires three clock cycles for 16-bit rank and two 
clock cycles for 8-bit rank. As the register MAR is restored and it is necessarily tra- 
versed by the data read or written to the RAM memory, the rank adaptation functions 
are carried out by MDR and the other registers do not need that adaptation anymore. 



Attachments 


Description 


attachments/xcpu/xcpu-e. v 


TKGate Verilog netlist source file. 


attachments/xcpu/xcpu-e.gm 


TKGate microcode and macrocode source 
file. 


attachments/xcpu/xcpu-e-terminal.vpd. 
tcl 


TCL/Tk script related to the terminal mod- 
ule TTY. 



Version "E" 

Figure 12.2. Simple CPU, version "E". 



733 




off 



CH 1 " 



CTRL 

(cM) 



flags 



— C 
~4? mD 



is — IN' 



OP 



mWE 
MEM d 

mA 
T 

S 3 
J 



.? C 



(PC) 
C A 



16 



c B 

D t 

(SP) 

C A 



D t 

(TMP) 
C A 



7^> 



A 

(FL) * 
D C 



HDD io_address 
IOA f 



c 4- 

c — 



IOA 

TTY 



s -» 

K -. 



RTC 



ft 


on 




off 



la c 



5* A la 



BUS 



(BP) 



(B) 



(A) 



A 


B 






Fo 


ALU c 




122:114 






Fi 


Q 







A * 


c 




D. 


(0) 




1 


c 



224 
1:0 



1:0 

198:195 



194:192 
1:0 



734 



Version "E" 



« 



12.1 General purpose modules 

The following modules were already used on the previous version of the project, 
except vrl, which is a counter able to increment or decrement only by 2" values. 

Figure 12.3. Rank reduction module: the module rank and its submodules. 

In Di 
V X V 

j« RNK16 




In 




RANK 


rank 




sign 


Out 






v 

Do 



Version "E" 



735 



Figure 12.4. Building Dn modules. 



Ck> 



C > 



module Dl 
(Dflip-flop) 




/ 2 

V 
Q 



: 




\ 


/ 






/ 





p 

V 



module D2 



i 




P 


Q 


D 




D1 


Q 


- Ck 




C 



A 
c 



Q P D 
D1 

Q g Ck 



-<Ck 



P 

V 





P 




Q 


D 

D2 


Q 


c 


Ck 



A 
c 



module D4 



■Q P D 
D2 

■Q ^ Ck 



-<Ck 



/ 4 

V 



736 



Version "E" 



Figure 12.5. Building DRw modules. 



D 

V 



module DR1 



Q -<r 



_Q 



+ v dd 











P 




Q 


D1 


D 




Q 




Ck 




c 





-<Ck 



A 
C 



module DR4 

Ck> 



D 

V 





7 2 







module DR2 



Ck>- 



-<L 



C >- 





D 


Ck 


DR1 l 


C 


Q 





D 

V 



c > 





D 


Ck 


DR1 l 


C 


Q 






o 

I I 



v 

Q 



<L 



-<L 



Q 



Version "E" 



737 



Figure 12.6. Building DHw modules. 



module E (enable) 



p >- 
s>- 

E>- 
R>- 

C >- 



> 



> 



> 



D 

V 



module DH1 

p >- 




> Q 



^ Q 



P > 



C > 



H > 



D 

V 



/2 



I 1 

1- o 



module DH2 



p > 



c >- 



H >" 



D H 




DH1 Q 


H C 





D 

V 



/4 



D P 




DH2 Q 


H C 






/2 



module DH4 



Q 




Q 



738 



Version 



Figure 12.7. Building vrw modules. 

$ 2 n increment/decrement 

D 

module "vrl" 



Co 



< — a= 



p 

v 









P 


Q 


D 




D1 


Q 


- Ck 




C 



A 
c 



L 

V 



module "vr4" 



Co < 



module "vr2" 



L 

V 



~™ minus 



-<Ck 



L 


m 


P 

D 
Ci 


Co 
Q 


vr2 


Ck 


P 


c 



A A 
Ck P 



F 




V 






/ 





Co < 



L 


m 


p 


Co 








D 




vr1 






Q 






Ci 


Ck 


p 




C 





/ 4 



A 
Ck 



L 

Co 
Q 

Ck P 



vr2 



A 
P 



3:2 4 

1:0 / <D 



"<Ci 



A 
C 



L 

' Co 
' Q 



vr1 



Ck P 



A 
C 



1 2 
1 -7^ 



<Ci 



Version "E" 



739 



Figure 12.8. Building VRw modules. 



Cdo ' 



post adder 

FA 

rO 



pre add load qii>- 



Cqo *^ 



pre adder 



FA 



v 

Q 



6 



"<qi 
-<Cqi 



-<di 

-<Cdi 



0 1 



p 

V 





P 




Q 




D 


Q 


C 


Ck 




t 






A 
C 





module VR1 



D 

V 



0 1 



-<L load 



<Ck 



Cqo 
Odo 



Q <- 



D 

V 



D 
' Cqo 



L qil 

qi ; 

di ; 

Cqi ~. 

cdi ; 
p c 



VR1 



A £ 



V qil 

V 



module VR2 



qii. 
qi 

Cdo vm cqi' 
_ Cdi 
k P C 



D L 

Cqo 

VR1 



A 
C 



7^<q 



2 

^^<di 



Cqd 

— C Cqi Cdo 
-<Cdi 

Q 



D 

V 

i" 



/2 



D L qil 
Cqo 9' 

VR2 



Cdo 
<Ck P 



A £ 



module VR4 



a L qil 
Cqo qi 

Cdo VR2 C q! 

^ Ck P C 



A 

c 



4 

^^<di 



-<Cqi 
-<Cdi 



740 



Version "E" 



12.2 Module "MEM' 



« 



The most important feature of this version is related to the memory management: the 
new module MEM contains the registers MAR , MDR and MIR which were previously 
autonomous. 

Figure 12.9. The module MEM. 




mWE mA mOE 



P = register PC 
I = register I 
J = register J 
S = register SP 
T = register TMP 



"5:0 MAR_ctrl 



0 load_address 



Rank 

W 


Addr 


RAM_WE 
RAM_A 


L 

Ck 


MAR 

(mar) 


RAMOE 
Busy 

b 

C 



+ + + + 



♦ + * 



p 1 


J 


S T 


nlA mWE mOE mD c c 








MEM OP 


A 




a 


cl i B 








+ * * 



RAM_OE 

MIR 

Busy (ir) 



RAM_D 
















R 


<- 












L 










RAM_OE 








sign 




5 




MDR 

<mdf) 


sjgri 








4 




rank 




, L 




3 


Busy 


*~ bus_write 


| rankU 




2 






bw 


bus_select o 


b 

Ck 


C A 


B 











0 0 



« 



12.2.1 Module "MAR" 

To access the RAM it is necessary to specify the address of the first byte, the rank 
starting from that address and the direction (read or write). First it is the mar module 
involved. 



Version "E" 

Figure 12.10. Module mar. 



741 



Addr 

V 



Ck> 



c > 




RAM_WE 
RAM A 



RAM_OE 
Busy 



Inside the above picture, should be noted the register used to store the memory address 
(on the left, type DR16). In the middle, the register of type vr2 is responsible to hold 
and count the rank: zero means one byte; one means two bytes; -1(1 h) means "stop". 
The middle register is not reset, but preset, so its initial condition is equal to the value 
-1. 

When the rank counter is not equal to -1 (1 1 2 ), then the rank counter is automatically 
decremented at each clock; after the rank counter reach the zero, it becomes equal to 
-1 and it stops changing. That is: when the requested rank is one (meaning two byte), 
its first value is one, then zero, then -1. When the rank counter is loaded with a valid 
rank it becomes busy and the output Busy is used to transmit this notion to the other 
modules (mdr and MIR); at the same time, the latch on the right (type DH1) holds the 
value received from the input W. 



742 



Version "E" 



The output RAM_A is obtained as the sum of the original address received from input 
Addr and the rank value, reported by the rank counter. That is: the first address output 
by Addr is the highest. The output b is used to let know the other modules which byte 
of the selected rank is considered during a particular time. The output RAM_OE is 
asserted (zero as the meaning is complemented) when the RAM is to be written, the 
busy line is active and the clock signal is low. 

The output RAM_OE is asserted (zero as the meaning is complemented) when the 
RAM is to be read: the output is negated (one) only when a write request is received. 



The RAM memory allows to be read in any condition, but when it comes the time 
to write it, it is necessary to activate the WE input only when the address is already 
available: that is why it is allowed to write only when the clock is low, as no change 
on the address can happen. 



12.2.2 Module "MIR" 

The MIR module {memory instruction register) is responsible for reading from mem- 
ory the next opcode to be executed. The current opcode occupy only one byte, but the 
MIR is prepared to accept a longer size: the b (byte) input line selects the byte that is 
currently read (the rank is specified to the mar module). The RAM_OE input line is 
asserted when the RAM is read and the Busy line is active when the RAM access cy- 
cle is not yet finished. The input line R should be active when the MIR module should 
read from RAM; then, when the read cycle starts, the Busy becomes active and the 
read request is hold by the DH1 module, up to the cycle end. 



Version "E" 

Figure 12.11. Module MIR. 



743 



RAM_ 


_D 




OP 


RAM. 


OE 


MIR 




Busy 




Or) 


R 


b 


Ck 


C 





read_0 



RAM D> 




-£> 7 -> D DR8 q 

Ck C 



8 



12.2.3 Module "MDR" 

The mdr module is a register used as buffer between the RAM memory and the CPU 
data bus. The difference from the MIR modules depends on the fact that it is connected 
to the two data busses and that can also write to the RAM. The mdr module is also 
responsible for rank adaptation of data, before writing to the data bus. 



« 



744 



Version "E" 



Figure 12.12. Module mdr. 



Busy>- 



H D 
- DH1 P 



< 



> 



4d DR8q 

Ck c 



< 



) DR8q 

Ck C 



15:8 - 



rank sign 



bsol 



1 



rank sign 

RANK 



In 



Out 



>- 

bus_write_A 

t> 



RAM_D 




R 


RAM_OE 




L 




MDR 


sign 


Busy 


(mdr) 


rank 






bw 


b 




bsol 


Ck 


0 A 


B 


t 


t t 


t 



« 



12.3 General purpose registers 

The registers are made in a simpler way compared to the previous version, because 
there is no rank problem: all data is moved at a 16-bit rank. There are two types of 
registers: the following figure shows the two external layouts. 



Version "E" 



745 



Figure 12.13. 16-bit registers: external appearance. 



bus select: 0-A; 1-B 
bus write 
load register 
6:3 pre-increment: -8.. +7 
Q pre-increment update 
Qi:s post-increment: -8.. +7 



connection to the "A " bus 



D register content copy 



c o clear j 
c i clock ! 



4- 


t 




4- t 


4- 


C 


D 


c 




C D 


c 








/ -► 


alu 




A 


t 


B 




A 


t 


.* 


4- 






4- 



a ^ u i5.o connection from the ALU 



^ test for debugging 



^i5o connection to the "B" bus 



746 



Version "E" 



Figure 12.14. 16-bit registers: internal structure. 



postjnc 




■3 12 



bus_select 



V 
V 

t 



-<c 



The C and FL registers are made with a slightly different module, where the "B" bus 
connection is named alu and is only able to receive data. 



Version "E" 

Figure 12.15. Alternative 16-bit registers structure. 



D 



2 



clock 



-* 1 



4 



^3 



D 


L 


qil 


Cqo 




qi 


Cdo 


VR16 


di 
Cqi 








Cdi 




k 


p 


c 



v dd 



v- 



bus_write_A 



prejnc 



pre_inc_update 



o . i 

J" 16 I 



0 

A 



/ 16 



A 
alu 



postjnc 



4 / 11:8 



/ 6:3 



747 



12 























ro 






b 




/ 


'a 



bus_select 



V 



1; 3 



-<c 



748 



Version "E' 



12.4 Module "ALU" and related submodules 



The module ALU, is the same as the previous version. 



Figure 12.16. Module ALU. 



CO: sign 
C1 : rank: 0=t 

C[8:6]=0: LOGIC 
C[8:6]=1:ADD, SUB 
C[8:6]=2: SHIFT, ROTATE CARRY 
C[8:6]=3: ROTATE 
C[8:6]=4: FLAG SET- RE SET 

LOGIC 

C[4:2H):q = a 
C[4:2]=1:q = aANDB 
C[4:2]=2:q = aORb 
C[4:2]=3:q = aXORb 
C[4:2]=4: q = NOT (a XOR b) 
C[4:2]=5:q = NOT (aORb] 
C[4:2]=6: q = NOT (a AND b) 
C[4:2]=7:q = NOTa 

ADD, SUB 
C2: subtract 
C3: use previous carry 

SHIFT 

C2: shift right 
C3: arithmetic shift 
C4: use previous carry 

ROTATE 
C2: rotate right 

FLAG SET-RESET 
C5=0: selected 
C5=1 : selected flag activation 
C[4:2]=0: carry 
C[4:2]=1:zero 
C[4:2]=2: negative 
C[4:2]=3: overflow 
C[4:2]=4: interrupt enable 
C[4:2]=5: not used 
C[4:2]=6: not used 
C[4:2]=7: not used 




The other components inside the ALU module are just the same as the previous ver- 
sion. 



Version "E" 



749 



Figure 12.17 '. Module LOGIC: the logic unit. 



C=0: q = a 
C=1:q = aAND B 
C=2: q = a OR b 
C=3: q = a XOR b 
C=4: q = NOT (a XOR b) 
C=5: q = NOT (a OR b) 
C=6: q - NOT (a AND b) 
C=7: q - NOT a 




V 

Q 



Figure 12.18. Module AS: addition and subtraction 



carry out 
borrow out 



B 

V 



16 



16 




0 



V V 

Co16 016 



V 



A B 

Co FA8 ci 

o 



subtract 



3 



carry_in_used 



overflow 



V v 



Co8 08 



-<c 



<Ci 

carry in 
borrow in 



750 



Version "E" 



Figure 12.19. Modules fa«: «-bit full adder. 



Co 



A 

V 



module FA1 



full adder 



9 

V 



-o 



-a 



V 
s 



module FA4 



Co <- 



O * 



B 

V 



A 

V 



/A 



<Ci 



Co < 
o ^ 



/2 



/T2 



A 


B 


Co 


FA1 Ci 


0 


S 



B 

V 



/4 



A 


B 




A 


B 


Co 


FA2 Ci 


+■ 


<- 


Co 


FA2 Ci 


0 


s 




<- 


0 


s 



A B 
Co FA1 Ci 
0 



-i o 

I I 



V 



-<Ci 



<Ci 



s 



Version "E" 

Figure 12.20. Module SH: bit shift. 



0 



0 



v 

Co16 



/ 


) 


\ 




/ 


'18 



la 


D 


lr 


Lo 




SH8 


Li 


Ri 






Ro 


O 




S 



arithmetic 



rank 



la 


D 


lr 


Lo 




Li 


Ri 


SH8 


Ro 




O 




S 



sh_left_and_carry_li :ft_8 



V 

016 



v 

s 



V 

08 



□ 



use_previous_carry 



■o 



-<Ci 



sh_righ t_and_carry_ri ght 



V 

Co8 



752 



Version "E' 



Figure 12.21. Module ROT: bit rotation. 



A 

V 



/ 16 



I I 

00 o 

Co 



I 



la 


D 


lr 


Lo 




Li 


Ri 


SH8 


Ro 




O 




S 



right 



rank 



rank 



r 



la 


D 


lr 


Lo 




Li 


Ri 


SH8 


Ro 




0 




S 



2 



-<c 



CO o 



The modules SH« are one-bit logic or arithmetic shifter. It all starts from module SHI, 
as the following figure shows. 



Version "E" 



753 



Figure 12.22. Module SHw: one-bit logic or arithmetic shift. 



D 

V 



left-out 



Ri>" 



right— in 



[1] 



r 



o 



la> 

0=logic shift 
1=arithmetic shift 



la 

V 



D 

V 



left-in 



<Li 

> Ro 

right-out 





'a 







module SH2 



module SHI 



[2] 



[1] Arithmetic shift conditions: 

- the requested shift is arithmetic; 

- the requested shift is to the right; 

- the most significant bit value is one. 
[2] Overflow conditions: 

- the requested shift is arithmetic; 

- the requested shift is to the left; 

- the most significant bit value is changed. 



<lr 

0=shift left 
1=shift right 



Lo <" 



Ri>- 



la 


D 


lr 


Lo 


SH1 


Li 


Ri 




Ro 


0 




S 



la D 

Lo 



I 3 



D 

V 



module SH4 



Lo <■ 
Ri>" 



la 


D 


lr 




Lo 


SH2 


Li 




<- 


Ri 




Ro 




-► 


0 




S 







lr 

V 



Li 



SH1 

Ri Ro 

O S 



lr 

v 



+ 






+ 


la 


D 


lr 


Lo 






Li 




SH2 






Ri 




Ro 


0 




S 







ro o 
J 



V 4 



o 



-<Li 
> RO 



— <Li 
> Ro 



754 



Version "E" 



Figure 12.23. Module fsr: flags set-reset. 




/ 


'16 




'i 6 




1 




0 





v 

Fo 



Version "E" 

12.5 Module "BUS' 



755 



« 



The module BUS is used to let the control unit to put a value inside the data-bus. This 
module BUS is the same as the previous version. 



Figure 12.24. Module BUS. 



bus select 



18 



bus write 




B A 



756 



Version "E" 



12.6 Module "IRQ" 

The IRQ module is the same as the previous version. All the details about the module 
functionality should be found at the previous version description. 

Figure 12.25. Module IRQ. 




0000— > 0100 
0001 — > 0100 
0010— > 0101 
0100— > 0110 
1000 — > 0111 



interrupt 
number 



Version "E" 



757 



12.7 Module "I VT" 

The ivt module is the same as the previous version. All the details about the module 
functionality should be found at the previous version description. 

Figure 12.26. Module ivt. 



« 



2 



IVT_start_address 



clock 



clear 



Ck 



DR16 L 



Q 



la lb 

V V 



inlerrupl_selecl 



ZTi 



interrupt 



"1 



' 16 

mterrupt_x_2 



A B 
Co FA16 Ci 

' 16 



-=> D 



load 



v- 



bus write 



-<C 



V 
t 



758 



Version "E" 



12.8 Module "RTC": real time clock 

The RTC module (real time clock) is just the same as the previous version: it generates 
a 1 Hz impulse, producing the hardware interrupt IRQO. All the details about the 
module functionality should be found at the previous version description. 



Listing 12.27. Module RTC: Verilog declaration. 



module RTC (T) ; 




output T; 




req p; 




always 




begin 




P = 0; 




$tkg$wait 


(500) ; 


p = 1; 




$tkg$wait 


(500) ; 


end 




assign T = p; 




endmodule 





Version "E" 



759 



12.9 Module "TTY" 

The tty module is just the same as the previous version: it is a textual screen- 
keyboard terminal interface. All the details about the module functionality should 
be found at the previous version description. 

Figure 12.28. Module tty. 



« 



Only the first 8 bits are read 
from the I/O device address, 




Listing 12.29. Module terminal: Verilog code. 



module terminal (K_DATA, K_REQ, K_ACK, S_DATA, S_REQ, S_ACK, CLR) ; 



output K_ACK; 
output S_ACK; 
output [7:0] K_DATA; 
input [7:0] S_DATA; 
input K_REQ; 



760 



Version "E" 



input S_REQ; 
input CLR; 
reg k_ready; 
reg [7:0] key ; 
reg s_ready; 

initial 
begin 

k_ready = 0; 

s_ready = 0; 

key = 0 ; 
end 

always 
begin 

@ (posedge CLR) 
k_ready = 0; 
s_ready = 0; 
key = 0; 
end 

initial $tkg$post ("TERMINAL", "%m") ; 

always 
begin 

@ (posedge K_REQ) ; 

# 5; 

key = $t kg$ recv ( " %m . KD " ) ; 

# 5; 

k_ready = l'bl; 

# 5; 

@ (negedge K_REQ) ; 

# 5; 

k_ready = 1'bO; 
end 

always 



Version "E" 



761 



begin 

@ (posedge S_REQ) ; 

# 5; 

$tkg$send ( "%m. SD", S_DATA) ; 

# 5; 

s_ready = l'bl; 

# 5; 

@ (negedge S_REQ) ; 

# 5; 

s_ready = 1'bO; 
end 



assign 
assign 
assign 



S_ACK = 
K_DATA = 
K ACK = 



s_ready; 

key; 
k_ready; 



endmodule 



Listing 12.30. File 'share/tkgate/vpd/terminal . tcl' for TCL interface. 

image create bitmap txtcurs -file "$bd/txtcurs .b" 

VPD :: register TERMINAL 
VPD::allow TERMINAL :: post 
VPD:: allow TERMINAL :: data 

namespace eval TERMINAL { 

# Public variables declarations: the variables $terminal_. . . 

# are arrays of which only the element $n is used; 

# that element identifies uniquely the working interface instance. 

variable terminal_w 
variable terminal_pos 
# 

variable KD 

# Function requested by TKGate to create the interface. 

proc post {n} { 

variable terminal_w 
variable terminal_pos 

# Create the window and save the object element in a $terminal_w array element . 

set terminal_w ($n) [VPD: : createWindow "TERMINAL $n" -shutdowncommand "TERMINAL :: impost $n"] 

# For convenience, copy the object reference inside the local 

# variable $w; then, the variable $w will be used as a reference to the object . 

set w $terminal_w ( $n ) 

text $w.txt -state disabled 

pack $w.txt 



762 



Version "E" 



# Put the cursor at the end of the displayed text . 

$w.txt image create end -image txtcurs 

# Bind the keyboard input, related to the object represented by 
§ $terminal_w ($n) , to the function sendChar. 

bind $w <KeyPress> "TERMINAL :: sendChar $n \"%A\"" 

# Open a reading channel, named «SD» (screen data), 

# and associate it to the function «data»; moreover, open a 

# writing channel, named «KD» (keyboard data) . 

if {[info exists : :tkgate_islnitialized] } { 
VPD: :outsignal $n.KD TERMINAL :: KD ( $n) 

VPD : : insignal $n.SD -command "TERMINAL :: data $n" -format %d 

} 

# Reset the character count, used to count the characters displayed 

# on screen. 

set terminal_pos ( $n) 0 

} 

# Function that receives the typing and put it into the 

# channel «KD», related to the current interface instance. 

proc sendChar {n key} { 
variable KD 

if { [string length $key ] == 1 } { 
binary scan $key c c 
set TERMINAL: : KD ($n) $c 

} 

} 

# Function that TKGate requires to destroy the interface. 

proc unpost {n} { 

variable terminal_w 
variable terminal_pos 
destroy $terminal_w ($n) 
destroy $terminal_pos ($n) 
unset terminal_w ( $n) 
unset terminal__pos ( $n) 

} 

# Function used to get the data to display on screen. 

proc data {n c} { 

variable terminal_w 
variable terminal_pos 

# For convenience, copy the object reference representing the 

# interface, inside the variable $w. 

set w $terminal_w ($n) 
catch { 

# The variable $c contains the character to display. 

if { $c == 7 } { 

# BEL 

bell 
return 

} elseif { $c == 127 | $c == 8 } { 

# DEL I BS 

if { $terminal_pos ($n) > 0 } { 

# Delete the last displayed character, but only if the 

# characters counter is greater than zero, otherwise 



Version "E" 



763 



# the cursor would disappear and the next characters 
§ would be located in an unvisible screen area . 

$w.txt configure -state normal 
$w.txt delete "end - 3 chars" 
$w.txt see end 

$w.txt configure -state disabled 

set terrainal_pos ( $n) [expr {$terminal_pos ( $n) - l}] 

} 

return 
} elseif { $c == 13 } { 
# Convert CR to LF. 

set c 10 

} 

# Convert the character number into a visible symbol . 

set x [format %c $c] 

# Display the symbol . 

$w.txt configure -state normal 
$w.txt insert "end - 2 chars" $x 
$w.txt see end 

$w.txt configure -state disabled 

# Update the displayed characters counter. 

set terminal_pos ( $n) [expr {$terminal_pos ($n) + l}] 

} 

} 

} 



12.10 Module "HDD 



The HDD module is just the same as the previous version: it is a simulated mass- 
memory drive whith the ability to handle eight units. All the details about the module 
functionality should be found at the previous version description. 



764 



Version "E" 



Figure 12.31. Module HDD. 



=E> 



f>HD- 



3D—D- 



=d- 



r=0 



2:0 3 



□ DR8 q 

Ck 5 



1 



L 

D DR3Q 
Ck C 



L 

d DR16q 

Ck C 



dDR10q 

Ck C 



D DR1 q 

Ck C 



Vdd 



Ck JK_ 
K r. 0 



REQ 
DRIVE 
SECTOR 
B\TE 
WRITE 



ACK CLR DATA_OUT 



When a request is not yet satisfied, the 
value that can be read at the output is 
negative, because the most significant byte 
has all bits set to one. 



Listing 12.32. Verilog code describing the module hd. 



module hd (DRIVE, SECTOR, BYTE, WRITE, DATA_IN, DATA_OUT, REQ, ACK, CLR); 

input [2:0] DRIVE; 

input WRITE, REQ, CLR; 

input [15:0] SECTOR; 

input [9:0] BYTE; 

input [7:0] DATA_IN; 

output [7:0] DATA_OUT; 

output ACK; 

// 



Version "E" 



765 



integer _data_out; 


integer _ack; 




// 




reg [7:0] buff er [ 0 : 1023 ] ; 


reg [8*24-1:0] filename = "hd0_sector_000000000 .mem" ; 


// 




integer i; 




integer sector_8 




integer sector_7 




integer sector_6 




integer sector_5 




integer sector_4 




integer sector_3 




integer sector_2 




integer sector_l 




integer sector_0 




integer x; 




// 




initial 




begin 




for (i=0; i<1024; i=i+l) 


begin 




// 




// Initial buffer reset with 00. 


// 




buffer 


[i] = 8'h00; 


end 




_ack = 0; 




_data_out = 


= 0; 


x = 0; 




end 




// 




always 




begin 




@ (posedge CLR) 


_ack = 0; 




_data_out = 


= 0; 


x = 0; 




end 




// 





766 



Version "E" 



// 
// 

always 
begin 
// 

// Start after a positive edge from REQ! . 

// 

@ (posedge REQ) ; 

# 10; 

// 

// Define the sector file name. 

// 

x = SECTOR; 
sector_0 = x%10; 
x = x/10; 
sector_l = x%10; 
x = x/10; 
sector_2 = x%10; 
x = x/10; 
sector_3 = x%10; 
x = x/10; 
sector_4 = x%10; 
x = x/10; 
sector_5 = x%10; 
x = x/10; 
sector_6 = x%10; 
x = x/10; 
sector_7 = x%10; 
x = x/10; 
sector_8 = x%10; 
// 

// The string starts from the right side and continues 
// to the left! 

// 

filename [12*8+7 : 12*8] = sector_8 + 8'd48; 
filename [11*8+7 : 11*8] = sector_7 + 8'd48; 
filename [10*8+7 : 10*8] = sector_6 + 8'd48; 
filename [9*8+7 : 9*8] = sector_5 + 8'd48; 
filename [8*8+7 : 8*8] = sector_4 + 8'd48; 
filename [7*8+7 : 7*8] = sector_3 + 8'd48; 



Version "E" 



767 



filename [6*8+7 : 6*8] = sector_2 + 8'd48; 




filename [5*8+7 : 5*8] = sector_l + 8'd48; 




filename [4*8+7 : 4*8] = sector_0 + 8'd48; 




// 




filename [21*8+7 : 21*8] = DRIVE + 8'd48; 




// 




if (WRITE) 




begin 




// 




// Put data inside the buffer. 




// 




buffer [BYTE] = DATA_IN; 




// 




// Save the buffer to disk. 




// Please remember that $writememh() 


must be enabled inside 


// TKGate configuration! 




// 




$writememh ( filename, buffer); 




// 




// Return the same data read. 




// 




_data_out = buffer [BYTE] ; 




end 




else 




begin 




// 




// Get data from disk to the buffer. 




// 




$readmemh (filename, buffer); 




// 




// Return the data required. 




// 




_data_out = buffer [BYTE] ; 




end 




// 




// Acknowledge. 




// 




_ack = 1; 




// 




// Wait the end of request (the negative 


edge) 



768 



Version "E" 



// before restarting the loop. 

// 

@ (negedge REQ) ; 

# 10; 

// 

// Now become ready again . 

// 

_ack = 0; 
end 
// 

assign DATA_0UT = _data_out; 

assign ACK = _ack; 

// 

endmodule 



12.11 Module "CTRL" 

The module CTRL is the same as almost the previous version, except for the name of 
the microprogram counter (now ^PC) and its size (11 bit). 



Version "E" 



769 



Figure 12.33. Module CTRL. 



interrupt set 



clock_pulse 




Ti Ck 

p Fie c <^<y 



Q To 
f 16 



V V 



-!>- 



D 

Cqo 


L 


qil 

qi 


Cdo 

%k 


VR11 

luPCi 
P 


di 
Cqi 
Cdi 

C 



uPC: microprogram counter 



^1 



ni<|o1 





6> 




> 




> 




> 










> 








D 




SI 

D 




il 

□ 




81 

D 




SI 


3 




SI 

□ 




SI 


J 



32 / 32 



/ * 32 



condi;ion_select 



/ 207 
'11 



12.11.1 Modules Tw" 

The modules Fw frequency divisors, made the same way as for the previous version. 



770 



Version "E' 



« 



Figure 12.34. Modules Dl and Tl: building a T flip-flop from a D flip-flop. 



module Dl: positive edge D flip-flop 



module Tl: T flip-flop 



p > 



Ck>- 




D>- 



C > 



> Q 



Or^O 



Q < 
Q < 



- Q 




Figure 12.35. Building the Fn modules. 
module Fl 



To 



Q 



P 

V 



Q P T 
T1 

Q q Ck 



module F2 



Q < / 



p 

v 



-<Ti 



-<Ck 



To < 











P 




Q 




Ti 


To 


F1 


Ck 






C 





A 
c 




Q 



1:0 



3:2 



2 



A 
C 



P 

V 



To < 





4 


Q 


P 

F2 


Ti 


To 


C 




Ck 









Q 


P 


Ti 




To 


F2 


Ck 






C 





module F4 

— <Ti 

1 <Ck 



A 
C 



-<Ti 



-<Ck 



12.11.2 Module "CLK_CLR" 

The module clk_CLR is responsible for the clock pulse generation and for the reset 
line, which is to be synchronized with the clock. The clock frequency may be con- 
trolled by the dip-switch at the top. It is important to remind that the control unit 
receives an inverted clock pulse, because the microcode data should be ready before 
the clock positive edge. This one is just the same as the previous version. 



Version "E" 



771 



Figure 12.36. Module clk_clr. 



0 -2,5 MHz 

1 -1,25 MHz 

2 -625 kHz 

3 -320 kHz 

4 -160 kHz 

5 -80 kHz 



6 -40 kHz 

7 -20 kHz 
8-10 kHz 

9 -5 kHz 

10 -2,5 kHz 

11 -1,25 kHz 



12 -625 Hz 

13 -320 Hz 

14 - 160 Hz 

15 - 80 Hz 




3* Clk 



> 



-<Rst 



D 



> CIr 



F0 - 5 MHz 

Highest frequency allowed, to prevent triggering undesired oscillations inside 
the T flip-flop chain, used to divide the frequency. 



Figure 12.37. Module one_up, used to start the oscillation inside the module 

CLK CLR. 



module one_up #(.W(1000)) (Z); 
output Z; 
reg Z; 



initial 
begin 

Z = 1'bO; 

$tkg$wait (W) ; 

Z = l'bl; 
end 



endmodule 



772 



Version "E" 



12.12 Memory and microcode fields 

The memory for this version of the project are described by the following lines of 
TKGate code. There are many blocks of memory for the microcode word, because 
every component connected to the data-bus can be controlled independently, as it is 
for the previous version of the project. 



Listing 12.38. Memory banks description for TKGate. 



map 


bank 


[9:0] 


Ctrl 


. map ; 


microcode 


bank 


[31 : 


0] 


Ctrl 


. microO ; 


microcode 


bank 


[63 : 


32] 


Ctrl 


. microl ; 


microcode 


bank 


[95 : 


64] 


Ctrl 


. micro2 ; 


microcode 


bank 


[127 


: 96] 


Ctrl 


. micro3 ; 


microcode 


bank 


[159 


: 128] 


Ctrl 


. micro4 ; 


microcode 


bank 


[191 


: 160] 


Ctrl 


. micro5 ; 


microcode 


bank 


[223 


: 192] 


Ctrl 


. micro6; 


macrocode 


bank 


[15 : 


0] 


ram; 





Listing 12.39. Fields of the microcode word, for TKGate. 



field 


Ctrl [1:0] 


= {nop=0, stop=l, load=2}; 




field 


j ump [5:2] 


= {false=0, carry_t=l, zero_t=2, negative_t 


= 3, 






overf low_t=4 , irq_enabled_t =5 , true=6, 








carry_f=9, zero_f=10, negat ive_f =1 1 , 








overf low_f =12 , irq_enabled_f =13} ; 




field 


addr [16: 6] 


= {ciao=0}; 




// 








field 


mar [22 : 17] 


= {load=0x0001, ram_write=0x0002, 








rank8=0, rankl 6=0x0 00 4 , 








p=0, i=8, j=16, s=24, t=32}; 




// 








field 


mdr [28 :23] 


= {a=0x0000, b=0x0001, bw=0x0002, 








rank8u=0, rankl 6=0x0004 , rank8s=0x0008 , 








load=0x0010, ram_read=0x0020}; 




// 








field 


mir [29:29] 


= {ram_read=0x000l}; 




// 








field 


pc [41 : 30] 


= {a=0x0000, b=0x0001, bw=0x0002, load=0x0004, 






qpl=0x0008, qp2=0x0010, qp3=0x0018, qp4= 


0x0020, 






qp5=0x0028, qp6=0x0030, qp7=0x0038, qm8= 


0x0040, 



Version "E" 



773 



qm7=0x0048, qm6=0x0050, qm5=0x0058, 

qm3=0x0068, qm2=0x0070, qml=0x0078, 

dpl=0x0100, dp2=0x0200, dp3=0x0300, 

dp5=0x0500, dp6=0x0600, dp7=0x0700, 

dm7=0x0900, dm6=0x0A00, dm5=0x0B00, 

dm3=0x0D00, dm2=0x0E00, dml=0x0F00 

// 

// Macro for Instruction fetch. 
// MAR <= PC++, MIR <= RAM 

// fl : mar=p mar=rank8 mar = load pc=dpl mir=ram_read; 

// 

field fetch [41:17] = {f 1=0x201001}; 
// 

field i[53:42] = {a=0x0000, b=0x0001, bw=0x0002, load 

qpl=0x0008, qp2=0x0010, qp3=0x0018, 

qp5=0x0028, qp6=0x0030, qp7=0x0038, 

qm7=0x0048, qm6=0x0050, qm5=0x0058, 

qm3=0x0068, qm2=0x0070, qml=0x0078, 

dpl=0x0100, dp2=0x0200, dp3=0x0300, 

dp5=0x0500, dp6=0x0600, dp7=0x0700, 

dm7=0x0900, dm6=0x0A00, dm5=0x0B00, 

dm3=0x0D00, dm2=0x0E00, dml=0x0F00 

= {a=0x0000, b=0x0001, bw=0x0002, load 

qpl=0x0008, qp2=0x0010, qp3=0x0018, 

qp5=0x0028, qp6=0x0030, qp7=0x0038, 

qm7=0x0048, qm6=0x0050, qm5=0x0058, 

qm3=0x0068, qm2=0x0070, qml=0x0078, 

dpl=0x0100, dp2=0x0200, dp3=0x0300, 

dp5=0x0500, dp6=0x0600, dp7=0x0700, 

dm7=0x0900, dm6=0x0A00, dm5=0x0B00, 

dm3=0x0D00, dm2=0x0E00, dml=0x0F00 

= {a=0x0000, b=0x0001, bw=0x0002, load 

qpl=0x0008, qp2=0x0010, qp3=0x0018, 

qp5=0x0028, qp6=0x0030, qp7=0x0038, 

qm7=0x0048, qm6=0x0050, qm5=0x0058, 

qm3=0x0068, qm2=0x0070, qml=0x0078, 

dpl=0x0100, dp2=0x0200, dp3=0x0300, 

dp5=0x0500, dp6=0x0600, dp7=0x0700, 



qm4=0x0060, 
qup=0x0080, 
dp4=0x0400, 
dm8=0x0800, 
dm4=0x0C00, 

}; 



// 

field j [65:54] 



// 

field sp [77 : 66] 



=0x0004, 
qp4=0x0020, 
qm8=0x0040, 
qm4=0x0060, 
qup=0x0080, 
dp4=0x0400, 
dm8=0x0800, 
dm4=0x0C00, 

}; 

=0x0004, 
qp4=0x0020, 
qm8=0x0040, 
qm4=0x0060, 
qup=0x0080, 
dp4=0x0400, 
dm8=0x0800, 
dm4=0x0C00, 

}; 

=0x0004, 
qp4=0x0020, 
qm8=0x0040, 
qm4=0x0060, 
qup=0x0080, 
dp4=0x0400, 
dm8=0x0800, 



774 



Version "E" 



dm7=0x0900, dm6=0x0A00, dm5=0x0B00, dm4=0x0C00, 
dm3=0x0D00, dm2=0x0E00, dml=0x0F00 }; 



// 

field tmp[89:78] 



// 

field fl [101 : 90] 



// 

field c [113: 102] 



{a=0x0000, b= 
qpl=0x0008, 
qp5=0x0028, 
qm7=0x0048, 
qm3=0x0068, 
dpl=0x0100, 
dp5=0x0500, 
dm7=0x0900, 
dm3=0x0D00, 

{a=0x0000, b= 
qpl=0x0008, 
qp5=0x0028, 
qm7=0x0048, 
qm3=0x0068, 
dpl=0x0100, 
dp5=0x0500, 
dm7=0x0900, 
dm3=0x0D00, 



0x0001, bw= 
qp2=0x0010, 
qp6=0x0030, 
qm6=0x0050, 
qm2=0x0070, 
dp2=0x0200, 
dp6=0x0600, 
dm6=0x0A00, 
dm2=0x0E00, 

0x0001, bw= 
qp2=0x0010, 
qp6=0x0030, 
qm6=0x0050, 
qm2=0x0070, 
dp2=0x0200, 
dp6=0x0600, 
dm6=0x0A00, 
dm2=0x0E00, 



0x0002, load 
qp3=0x0018, 
qp7=0x0038, 
qm5=0x0058, 
qml=0x0078, 
dp3=0x0300, 
dp7=0x0700, 
dm5=0x0B00, 
dml=0x0F00 

0x0002, load 
qp3=0x0018, 
qp7=0x0038, 
qm5=0x0058, 
qml=0x0078, 
dp3=0x0300, 
dp7=0x0700, 
dm5=0x0B00, 
dml=0x0F00 



=0x0004, 
qp4=0x0020, 
qm8=0x0040, 
qm4=0x0060, 
qup=0x0080, 
dp4=0x0400, 
dm8=0x0800, 
dm4=0x0C00, 

}; 

=0x0004, 
qp4=0x0020, 
qm8=0x0040, 
qm4=0x0060, 
qup=0x0080, 
dp4=0x0400, 
dm8=0x0800, 
dm4=0x0C00, 

}; 



{a=0x0000, b= 


= 0x0001, bw= 


0x0002, load= 


= 0x0004, 


qpl 


=0x0008, 


qp2 


=0x0010, 


qp3 


=0x0018, 


qp4 = 


0x0020, 


qp5 


=0x0028, 


qp6 


=0x0030, 


qp7 


=0x0038, 


qm8= 


0x0040, 


qm7 


=0x0048, 


qm6 


=0x0050, 


qm5 


=0x0058, 


qm4 = 


0x0060, 


qm3 


=0x0068, 


qm2 


=0x0070, 


qml 


=0x0078, 


qup= 


0x0080, 


dpi 


=0x0100, 


dp 2 


=0x0200, 


dp 3 


=0x0300, 


dp4 = 


0x0400, 


dp 5 


=0x0500, 


dp 6 


=0x0600, 


dp 7 


=0x0700, 


dm8= 


0x0800, 


dm 7 


=0x0900, 


dm 6 


=0x0A00, 


dm5 


=0x0B00, 


dm4 = 


OxOCOO, 


dm3 


=0x0D00, 


dm2 


=0x0E00, 


dml 


=0x0F00 ] 







// 

field alu[122:114] = 



{rank8u=0, rank8s=l, rankl6=2, 
a=0, and=4, or=8, xor=12, 
nxor=16, nor=20, nand=24, not=28, 
add=64, sub=68, addc=72, subb=76, 
lshl=128, lshr=132, ashl=136, ashr=140, 
rotcl=144, rotcr=148, 
rotl=192, rotr=196, 



Version "E" 



775 



clearc=256, clearz=260, clearn=264, 
clearo=268, cleari=272, 
setc=288, setz=292, setn=296, 
seto=300, seti=304}; 



// 

field a [134 : 123] 



// 

field b[146: 135] 



// 

field bp[158:147] 



// 

field bus [176: 159] 
// 

field ioa[188:177] 



{a=0x0000, b= 
qpl=0x0008, 
qp5=0x0028, 
qm7=0x0048, 
qm3=0x0068, 
dpl=0x0100, 
dp5=0x0500, 
dm7=0x0900, 
dm3=0x0D00, 

{a=0x0000, b= 
qpl=0x0008, 
qp5=0x0028, 
qm7=0x0048, 
qm3=0x0068, 
dpl=0x0100, 
dp5=0x0500, 
dm7=0x0900, 
dm3=0x0D00, 

{a=0x0000, b= 
qpl=0x0008, 
qp5=0x0028, 
qm7=0x0048, 
qm3=0x0068, 
dpl=0x0100, 
dp5=0x0500, 
dm7=0x0900, 
dm3=0x0D00, 



0x0001, bw= 
qp2=0x0010, 
qp6=0x0030, 
qm6=0x0050, 
qm2=0x0070, 
dp2=0x0200, 
dp6=0x0600, 
dm6=0x0A00, 
dm2=0x0E00, 

0x0001, bw= 
qp2=0x0010, 
qp6=0x0030, 
qm6=0x0050, 
qm2=0x0070, 
dp2=0x0200, 
dp6=0x0600, 
dm6=0x0A00, 
dm2=0x0E00, 

0x0001, bw= 
qp2=0x0010, 
qp6=0x0030, 
qm6=0x0050, 
qm2=0x0070, 
dp2=0x0200, 
dp6=0x0600, 
dm6=0x0A00, 
dm2=0x0E00, 



0x0002, load 
qp3=0x0018, 
qp7=0x0038, 
qm5=0x0058, 
qml=0x0078, 
dp3=0x0300, 
dp7=0x0700, 
dm5=0x0B00, 
dml=0x0F00 

0x0002, load 
qp3=0x0018, 
qp7=0x0038, 
qm5=0x0058, 
qml=0x0078, 
dp3=0x0300, 
dp7=0x0700, 
dm5=0x0B00, 
dml=0x0F00 

0x0002, load 
qp3=0x0018, 
qp7=0x0038, 
qm5=0x0058, 
qml=0x0078, 
dp3=0x0300, 
dp7=0x0700, 
dm5=0x0B00, 
dml=0x0F00 



=0x0004, 
qp4=0x0020, 
qm8=0x0040, 
qm4=0x0060, 
qup=0x0080, 
dp4=0x0400, 
dm8=0x0800, 
dm4=0x0C00, 

}; 

=0x0004, 
qp4=0x0020, 
qm8=0x0040, 
qm4=0x0060, 
qup=0x0080, 
dp4=0x0400, 
dm8=0x0800, 
dm4=0x0C00, 

}; 

=0x0004, 
qp4=0x0020, 
qm8=0x0040, 
qm4=0x0060, 
qup=0x0080, 
dp4=0x0400, 
dm8=0x0800, 
dm4=0x0C00, 

}; 



{bw=0xl0000, a=0, b=0x20000}; 

{a=0x0000, b=0x0001, bw=0x0002, load=0x0004, 
qpl=0x0008, qp2=0x0010, qp3=0x0018, qp4=0x0020, 
qp5=0x0028, qp6=0x0030, qp7=0x0038, qm8=0x0040, 



776 



Version "E" 



qm7 


=0x0048, 


qm6 


=0x0050, 


qm5 


=0x0058, 


qm4 = 


0x0060, 


qm3 


=0x0068, 


qm2 


=0x0070, 


qml 


=0x0078, 


qup= 


0x0080, 


dpi 


=0x0100, 


dp 2 


=0x0200, 


dp 3 


=0x0300, 


dp4 = 


0x0400, 


dp 5 


=0x0500, 


dp 6 


=0x0600, 


dp 7 


=0x0700, 


dm8= 


0x0800, 


dm 7 


=0x0900, 


dm 6 


=0x0A00, 


dm5 


=0x0B00, 


dm4 = 


OxOCOO, 


dm 3 


=0x0D00, 


dm2 


=0x0E00, 


dml 


=0x0F00 


u 





// 

field ivt [191: 189] = {bw=l, load=2, int_a=0, int_b=4}; 
// 

field irq[194:192] = {bw=l, mask_load=2, irq_done=4}; 
// 

field ioc[198:195] = {load=l, bw=2, req=4, isack=8}; 



« 



12.13 Opcodes 

The opcodes are exactly the same as the previous version. For convenience, the fol- 
lowing table shows the opcode organization. 

Table 12.40. Opcodes. 



0x00 


00 


0x40 


010000. . 


0x44 


010001. . 


0x48 


010010. . 


0x4C 


0100110. 


0x4E 


0100111. 


0x50 


010100. . 


0x54 


010101. . 


0x58 


010110. . 


0x5C 


0101110. 


0x5E 


0101111. 


0x60 


01100. . . 


0x68 


01101. . . 


0x70 


OHIO. . . 


0x78 


01111. . . 


0x80 


10000000 


0x81 


10000001 


0x82 


1000001. 


0x84 


1000010. 


0x86 


1000011. 


0x88 


1000100. 



byteO 



byte 1 



byte 2 



b7 


b6 


b5 


b4 


b3 


b2 


b1 


bO 




cp % % 


% 


% 


cp n % 


A, B, I, J 


const16 


cp (%) % 


(I- J) 


A, B 




cp % (%) 


A, B 


(I, J) 


cp n (%) 


(I, J) 


const16 


cp (%) (%) 


(I, J) 






cp8 n % 


A B, I, J 


const8 




cp8 (%) % 


(I, J) 


AB 






cp8 % (%) 


A, B 


(I, J) 


cp8 n (%) 


(I, J) 


const8 




cp8 (%) (%) 


(I, J) 






byte 0 


byte 1 byte 2 


b7 


b6 


b5 


b4 


b3 


b2 


b1 


bO 




push % 


% 


push8 % 


% 


pop % 


% 


pop8 % 


% 


push n 


const16 


push8 n 


const8 




push (%) 


(I, J) 






push8 (%) 


(I, J) 




pop (%) 


(I, J) 


pop8 (%) 


(I, J) 



byte 3 



byte 3 



Version "E" 



byte 0 byte 1 byte 2 byte 3 







b7 


b6 


b5 


b4 


b3 


b2 


b1 


bO 




0x90 


10010. . . 


jump%flag 0|1 #ref 


%flag 


TRUE 


#ref 


0x98 


1001100. 


equal, not 


NOT 




0x9A 


1001101. 


and 


NOT 




0x9C 


1001110. 


or 


NOT 




0x9E 


1001111. 


xor 


NOT 




OxAO 


1010000. 


add, sub 


sub 




0xA2 


1010001 . 


addc, subb 


sub 




0xA4 


1010010. 


Ish 


right 




0xA6 


1010011. 


ash 


right 




0xA8 


1010100. 


rote 


right 




OxAA 


1010101. 


rot 


right 





Ox AC 
OxAE 
OxBO 
0xB2 
0xB4 
0xB6 
0xB8 



1010110. 
1010111. 
1011000. 
1011001. 
1011010. 
1011011. 
101110. . 



byteO 



b7 b6 b5 b4 b3 b2 


b1 


bO 


add8, sub8 


sub 


add8c, sub8b 


sub 


Ish8 


right 


ash8 


right 


rot8c 


right 


rot8 


right 


cast 


sign 


A,B 



byte 1 



byte 2 



byte 3 



OxBC 
OxBE 
OxCO 
0xC2 
0xC4 
0xC6 
0xC8 
OxCA 
OxCC 
OxCE 



1011110. 
1011111. 
1100000. 
1100001. 
1100010. 
1100011. 
1100100. 
1100101. 
1100110. 
1100111. 



byteO 



b7 b6 b5 b4 b3 b2 b1 


bO 


equals, nots 


NOT 


ands 


NOT 


ors 


NOT 


xors 


NOT 


adds, subs 


sub 


addes, subbs 


sub 


Ishls, Ishrs 


right 


ashls, ashrs 


right 


rotcls, rotcrs 


right 


rotls, rotrs 


right 



byte 1 



byte 2 



byte 3 



byteO 



OxDO 
0xD2 
0xD4 
0xD6 
0xD8 
OxDA 
OxDC 



1101000. 
1101001. 
1101010. 
1101011. 
1101100. 
1101101. 
1101110. 



b7 b6 b5 b4 b3 b2 b1 


bO 


add8s, sub8s 


sub 


add8cs, sub8bs 


sub 


Ish8ls, Ish8rs 


right 


ash8ls, ash8rs 


right 


rot8cls, rot8crs 


right 


rot8ls, rot8rs 


right 


casts 


sign 



byte 1 



byte 2 



byte 3 



778 



Version "E' 



OxDE 


11011110 


OxDF 


11011111 


OxEO 


-i -i -i r~\ f~\ s~\ r\ s~\ 

11100000 


OxEl 


11100001 


0xE2 


11100010 


0xE3 


11100011 


0xE4 


1110010 . 


0xE6 


1110011 . 


0xE8 


1110100 . 


OxEA 


1110101. 


OxEC 


mono. 


OxEE 


1110111. 


OxFO 


11110000 


OxFl 


11110001 


0xF2 


1111001 . 


0xF4 


1111010 . 


0xF6 


1111011 . 




1111100 . 


Ox FA 


1111101. 


OxFC 


1111110. 


OxFE 


11111110 


OxFF 


11111111 



byte 0 


byte 1 byte 2 


byte 3 


b7 b6 b5 b4 b3 b2 b1 


bO 






call 


#ref 


return 






int 


int 




iret 






imrl 


mask 




ivtl 


#ref 


flag_iO|1 


set 




flag_c 0|1 


set 






in n % 


A, B 


port 




in n (%) 


(I, J) 


port 


out % n 


A, B 


port 


out (%) n 


(I, J) 


port 


if_ackjump 


port 


#ref 


if ack call 


port 


#ref 



byteO 



byte 1 



byte 2 



b7 b6 b5 b4 b3 b2 b1 


bO 




cmpr, testr 


test 


cmpi, testi 


test 


cmps, tests 


test 


cmp8i, test8i 


test 


cmp8s, test8s 


test 


call (%) 


I, J 


jump 


#ref | 


stop 





byte 3 



Table 12.41. Macrocode syntax: it is the same as the previous version. 



Macrocode syntax 


Description 


nop 


Not operate. 


cp %src , %dst 


Copy the src register content inside the dst 
register. Allowed registers are: I, J,A, B, 
BP, SP, C, FL. 


cp nl6 , %dst 


Assign a 16-bit constant to a register. Al- 
lowed destination registers are: I,J,A,B. 


cp (%l|%J), %A|%B 


Assign to register A or B the 16-bit value 
contained in memory at the address al- 
ready available from register I or J. 


cp %A | %B, (%I | %J) 


Copy in memory the 16-bit value of regis- 
ter A or B, to the location represented by 
the register / or /. 


cp nl6, (%I | %J) 


Assign in memory the 16-bit constant, to 
the location represented by the register / 
or J. 



Version "E" 



779 



Macrocode syntax 


Description 




Copy the 16-bit memory content at the 


cp (%I) 


cIUUICjj ICJJICdCllLCLl Uj ICglMCl 1 , LU L11C 

memory location represented oy me reg- 
ister J. 




Copy the 16-bit memory content at the 


cp (%J) 


aaaress represented oy register j , to tne 
memory location represented by the reg- 
ister /. 


cp8 n8 , %dst 


Assign a 8-bit constant to a register. Al- 
lowed destination registers are: I,J,A,B. 




Assign to register A or B the 8-bit value 


cp8 (%l|%J), %A|%B 


contained in memory at the address al- 
ready available from register I or J. 


cp8 %A | %B, (%I | %J) 


Conv in memorv the 8-bit value of register 
A or 5, to the location represented by the 
register I or J. 


CD 8 «5, (%I 1 %J) 


A cci cr n i n m pm rvr\7 tnp >\_ ni t crwi c1~iin1~ tn 
.rYaMgll 111 lllClllUlj L11C O UH CUlldLcillL, l\J 

tne location represented oy tne register i 
or J. 




Copy the 8-bit memory content at the 


cp8 (%I) 


'.\ H H tv*o c ranrpc p»n t^H r\\7 t^cti ct^T* T tn t n 
cIUUICjj ICpiC^CllLCU- Uj ICglMCl 1 , LU L11C 

memory location represented oy tne reg- 
ister J. 




Copy the 8-bit memory content at the ad- 


cp8 (%J) 


dress represented oy register j , to tne 
iiieiiiuiy lucdiiuii icpicsciiLcd vy uie icg- 
ister /. 


push reg 


Push at the top of the stack the 16-bit value 


contained inside the register. 


pop reg 


Pop from the stack a 16-bit value that is 


then assigned to the register. 


push8 reg 


Push at the top of the stack the 8-bit value 


contained inside the register. 


pop 8 reg 


Pop from the stack a 8 -bit value that is then 


assigned to the register. 



780 



Version "E" 



Macrocode syntax 


Description 


push nl6 


Push at the top of the stack the 16-bit con- 
stant. 


push n8 


Push at the top of the stack the 8-bit con- 
stant. 


push (%I | %J) 


Push at the ton of the stack the 1 6-bit value 
contained in memory, at the location rep- 
resented by register I or J. 


push (%I | %J) 


Push at the ton of the stack the 1 6-bit value 
contained in memory, at the location rep- 
resented by register I or J. 


push8 (%l|%J) 


Push at the ton of the stack the 8-bit value 

A V-*» LI 1 1 t~ I V L11V IV l_y V ' 1 lllv L.J 111V \~J L / 1 V V tl 1 LI ^/ 

contained in memory, at the location rep- 
resented by register I or J. 


pop (%I | %J) 


Pod from the ton of the stack a 1 6-bit that 

A 1 X 1X1 lllv IV V~J X lllv U tU-VXV 1.1 1_ V/ L/ll- 111 IX V 

is then copied at the memory location rep- 
resented by register I or J. 


pop8 (%l|%J) 


Pod from the ton of the stack a 8-bit that is 

A l_» 1 X 1X1 111V IV V~J VX lllv JIUV1V IX 1 V llllll 1U 

then copied at the memory location repre- 
sented by register I or J. 


jump #ref 


Jump to the address specified. 


jump %carry | %borrow^ 

| %zero | %negative^ 
| ^overflow, ^ 
^ 0|l, #ref 


Conditional jump. The first argument is 
a pseudo-register that selects the flag; the 
second argument means the value that the 
flag should have; the third argument is the 
address where the jump should go if the 
condition is met. 


equal 


C =A, updating the flags status 


not 


C = ~A, updating the flags status (one's 
complement). 


and 


C =A & B, updating the flags. 


nand 


C = ~(A & B), updating the flags. 



Version "E" 



781 



Macrocode syntax 


Description 


or 


C = A 1 B, updating the flags. 


nor 


C = ~(A 1 B), updating the flags. 


xor 


C = A A B, updating the flags. 


nxor 


C = ~(A A B), updating the flags. 


add 


C =A + B, updating the flags, 16-bit. 


sub 


C =A - B, updating the flags, 16-bit. 


addc 


C = A + B + carry, updating the flags, 16- 
bit. 


subb 


C = A - B - borrow, updating the flags, 
16-bit. 


lshl 


C = lshl(A), updating the flags: logic shift 
left, 16-bit. 


lshr 


C = lshr(A), updating the flags: logic shift 
right, 16-bit. 


ashl 


C = ashl(A), updating the flags: arithmetic 
shift left, 16-bit. 


ashr 


C = ashr(A), updating the flags: arithmetic 
shift right, 16-bit. 


rot cl 


C = rotcl(A), updating the flags: rotation 
left whith carry, 16-bit. 


rot cr 


C = rotcr(A), updating the flags: rotation 
right whith carry, 16-bit. 


rot 1 


C = rotl(A), updating the flags: rotation 
left, 16-bit. 


rot r 


C = rotr(A), updating the flags: rotation 
right, 16-bit. 



782 



Version "E" 



Macrocode syntax 


Description 


add8 


C =A + B, updating the flags, 8-bit. 


sub8 


C =A - B, updating the flags, 8-bit. 


add8c 


C = A + B + carry, updating the flags, 8- 
bit. 


sub8b 


C = A - B - borrow, updating the flags, 
8-bit. 


lsh81 


C = lsh81(A), updating the flags: logic 
shift left, 8-bit. 


lsh8r 


C = lsh8r(A), updating the flags: logic 
shift right, 8-bit. 


ash81 


C = ash81(A), updating the flags: arith- 
metic shift left, 8 -bit. 


ash8r 


C = ash8r(A), updating the flags: arith- 
metic shift right, 8-bit. 


rot 8cl 


C = rot8cl(A), updating the flags: rotation 
left whith carry, 8-bit. 


rot 8cr 


C = rot8cr(A), updating the flags: rotation 
right whith carry, 8 -bit. 


rot81 


C = rot81(A), updating the flags: rotation 
left, 8-bit. 


rot 8r 


C = rot8r(A), updating the flags: rotation 
right, 8 -bit. 


cast 0 | 1 %A | %B 


Adapt the register value to 8-bit, unsigned 
or signed, depending on the first argument. 


equals 


Read the 16-bit value on top of the stack 
and update the flags. 


not s 


Read the 16-bit value on top of the stack 
and replace it with the one's complement, 
updating the flags. 



Version "E" 



783 



Macrocode syntax 



Description 



ands 



Pop two 16-bit values from the top of the 
stack and push the bitwise AND of them, 
updating the flags, the registers A and B 
are overwritten. 



nands 



Pop two 16-bit values from the top of the 
stack and push the bitwise NAND of them, 
updating the flags, the registers A and B 
are overwritten. 



ors 



nors 



Pop two 16-bit values from the top of the 
stack and push the bitwise OR of them, up- 
dating the flags, the registers A and B are 
overwritten. 

Pop two 16-bit values from the top of the 
stack and push the bitwise NOR of them, 
updating the flags, the registers A and B 
are overwritten. 



xor s 



Pop two 16-bit values from the top of the 
stack and push the bitwise XOR of them, 
updating the flags, the registers A and B 
are overwritten. 



nxors 



Pop two 16-bit values from the top of the 
stack and push the bitwise NXOR of them, 
updating the flags, the registers A and B 
are overwritten. 



adds 



Pop two 16-bit values from the top of the 
stack and push the sum of them, updating 
the flags. To do the calculation, the regis- 
ters A and B are overwritten. 



subs 



addcs 



Pop a 16-bit values from the top of the 
stack and put it inside the register B ; then 
pop another 16-bit value and put inside 
the register A; then calculate A-B updat- 
ing the flags and push the result inside the 
stack again. 

Pop two 16-bit values from the top of the 
stack and push the sum with carry of them, 
updating the flags. To do the calculation, 
the registers A and B are overwritten. 



784 



Version "E" 



Macrocode syntax 



Description 



subbs 



Pop a 16-bit values from the top of the 
stack and put it inside the register B ; then 
pop another 16-bit value and put inside the 
register A; then calculate A -B -borrow 
updating the flags and push the result in- 
side the stack again. 



lshls 



lshrs 



ashls 



Pop a 16-bit values from the top of the 
stack and push the logic shift left of it, up- 
dating the flags. 

Pop a 16-bit values from the top of the 
stack and push the logic shift right of it, 
updating the flags. 

Pop a 16-bit values from the top of the 
stack and push the arithmetic shift left of 
it, updating the flags. 



ashrs 



Pop a 16-bit values from the top of the 
stack and push the arithmetic shift right of 
it, updating the flags. 



rot els 



Pop a 16-bit values from the top of the 
stack and push the rotation left with carry 
of it, updating the flags. 



rotors 



Pop a 16-bit values from the top of the 
stack and push the rotation right with carry 
of it, updating the flags. 



rot Is 



Pop a 16-bit values from the top of the 
stack and push the rotation left of it, up- 
dating the flags. 



rot rs 



Pop a 16-bit values from the top of the 
stack and push the rotation right of it, up- 
dating the flags. 



add8s 



Pop two 8-bit values from the top of the 
stack and push the sum of them, updating 
the flags. To do the calculation, the regis- 
ters A and B are overwritten. 



Version "E" 



785 



Macrocode syntax 



Description 



sub8s 



Pop a 8-bit values from the top of the stack 
and put it inside the register B ; then pop 
another 8-bit value and put inside the reg- 
ister A; then calculate A -B updating the 
flags and push the result inside the stack 
again. 



add8cs 



sub8bs 



Pop two 8-bit values from the top of the 
stack and push the sum with carry of them, 
updating the flags. To do the calculation, 
the registers A and B are overwritten. 
Pop a 8-bit values from the top of the stack 
and put it inside the register B ; then pop 
another 8-bit value and put inside the reg- 
ister A; then calculate A -B -borrow up- 
dating the flags and push the result inside 
the stack again. 



Ish81s 



Pop a 8-bit values from the top of the stack 
and push the logic shift left of it, updating 
the flags. 



Ish8rs 



Pop a 8-bit values from the top of the stack 
and push the logic shift right of it, updating 
the flags. 



ash81s 



Pop a 8-bit values from the top of the stack 
and push the arithmetic shift left of it, up- 
dating the flags. 



ash8r s 



rotc81s 



rot c8rs 



Pop a 8-bit values from the top of the stack 
and push the arithmetic shift right of it, up- 
dating the flags. 

Pop a 8-bit values from the top of the stack 
and push the rotation left with carry of it, 
updating the flags. 

Pop a 8-bit values from the top of the stack 
and push the rotation right with carry of it, 
updating the flags. 



rot 81s 



Pop a 8-bit values from the top of the stack 
and push the rotation left of it, updating the 
flags. 



786 



Version "E" 



Macrocode syntax 


Description 


rot 8r s 


Pod a 8-bit values from the ton of the stack 
and push the rotation right of it, updating 
the flags. 


casts 0 | 1 


Pop a 16-bit value from the top of the stack 
and Dush the same value adanted to 8-bit 
unsigned or signed, depending on the ar- 
gument. 


call #ref 


Call the nrocedure that starts at the arsu- 

V/Ull U1V l_/A V-'V-' V*- VIA V- - lllLil JIU1 I J III l>llv HI V* 

ment reference: the registers FL and PC 
are pushed inside the stack. 


call (%I|%J) 


Call the procedure that starts at the posi- 
tion contamea msiae register 1 or j . tne 
registers FL and PC are pushed inside the 
stack. 


return 


Return from a previous call: the registers 
PC and FL are retrieved from the stack. 


int n8 


Software interrupt call: the registers FL 
and PC are pushed inside the stack. 


iret 


Return from an interrupt: the registers PC 
and FL are retrieved from the stack. 


imrl n8 


Load the IMR: interrupt mask register. 


ivtl #ref 


Load the TVT' interrunt vector table The 

-1 — J V' U1V AT A • AAA Wvl A VI Y-S X, V V-* V IV' 1 ILiUlV • A 11V 

argument is the interrupt vector table start 
address in memory. 


f lag_i 0 | 1 


Reset or set the flag that allow the hard- 
ware interrupts. 


f lag_c 0 | 1 


Reset or set the carry (borrow) flag. 


in n8, %A | %B 


Read from the I/O address specified, a byte 
that is copied inside register A or B. 


in n8, (%I | %J) 


Read from the I/O address specified, a byte 
that is copied in memory, at the address 
specified by register I or J. 



Version "E" 



787 



Macrocode syntax 



Description 



out %A|%B, n8 



Write to the I/O address specified, a byte 
that is read from register A or B. 



out (%I I %J) , n8 



Write to the I/O address specified, a byte 
that is read from memory, at the address 
specified by register I or J. 



ifack_jump n8 , #ref 



ifack_call n8 , #ref 



If the I/O port gives an acknoledge report, 
then jump to the specified address. 

If the I/O port gives an acknoledge report, 
then call the specified procedure. 



cmpr 



Calculate A -B, updating the flags, with- 
out modifying the accumulator. 



testr 



Calculate A&B (bitwise AND), updating 
the flags, without modifying the accumu- 
lator. 



cmpi 



Load A with the value contained in mem- 
ory at the address represented by the reg- 
ister /; load B with the value contained in 
memory at the address represented by the 
register J; then calculate A -B, updating 
the flags, without modifying the accumu- 
lator. 



test i 



cmps 



Load A with the value contained in mem- 
ory at the address represented by the reg- 
ister /; load B with the value contained in 
memory at the address represented by the 
register J; then calculate A&B (bitwise 
AND), updating the flags, without modi- 
fying the accumulator. 
Read from the top of the stack a 16-bit 
value and put it inside the register B ; read 
from the stack, just under the previous 
value, a 16-bit value and put it inside the 
register A; then calculate A -B, updating 
the flags, without modifying the accumu- 
lator. 



788 



Version "E" 



Macrocode syntax 



Description 



tests 



Read from the top of the stack a 16-bit 
value and put it inside the register B ; read 
from the stack, just under the previous 
value, a 16-bit value and put it inside the 
register A; then calculate A&B, updating 
the flags, without modifying the accumu- 
lator. 



cmp8r 



Calculate 8-bit A -B, updating the flags, 
without modifying the accumulator. 



test 8r 



Calculate 8-bit A&B (bitwise AND), up- 
dating the flags, without modifying the ac- 
cumulator. 



cmp8i 



Load 8 -bit inside A with the value con- 
tained in memory at the address repre- 
sented by the register /; load 8-bit inside B 
with the value contained in memory at the 
address represented by the register J; then 
calculate A -B, updating the flags, without 
modifying the accumulator. 



test 8i 



Load 8 -bit inside A with the value con- 
tained in memory at the address repre- 
sented by the register /; load 8-bit inside B 
with the value contained in memory at the 
address represented by the register J; then 
calculate A&B, updating the flags, with- 
out modifying the accumulator. 



cmp8s 



Read from the top of the stack a 8 -bit value 
and put it inside the register B ; read from 
the stack, just under the previous value, a 
8 -bit value and put it inside the register 
A ; then calculate A -B, updating the flags, 
without modifying the accumulator. 



Version "E" 



789 



Macrocode syntax 


Description 


test 8s 


Read from the top of the stack a 8 -bit value 
and put it inside the register B ; read from 
the stack, just under the previous value, a 
8-bit value and nut it inside the register 

V_J C 1 V T HI Li V Lillvi L/ Vit X V 111 J1V1V H1W IV-'&.lUW-'l 

A ; then calculate A &B , updating the flags, 
without modifying the accumulator. 


stop 


Stop the system. 



Listing 12.42. Registers, flags and opcodes encoded for TKGate. This encoding 
is the same as the previous version, because the opcodes do not change. 

registers 1=0, J=l, A=2, B=3, BP=4, SP=5, C=6, FL=7; 

registers carry=0, borrow=0, zero=l, negative=2, overflow=3; 

// 

op nop { 

map nop: 0x00; // not operate 

operands { - = { +0=0x00; }; }; 

}; 
// 



op cp { 



// 












00 




cp 


%, % 






map 


nop : 




0x00; 


// 


00000000 




cp 


%J, 


%I 


= nop 


map 


cp_ 


i_ 


_j : 


0x01; 


// 


00000001 




cp 


%I, 


%J 




map 


cp_ 


i_ 


_a : 


0x02; 


// 


00000010 




cp 


%I, 


%A 




map 


cp_ 


i_ 


_b: 


0x0 3; 


// 


00000011 




cp 


%I, 


%B 




map 


cp_ 


i_ 


_bp : 


0x04; 


// 


00000100 




cp 


%I, 


%BP 




map 


cp_ 


i_ 


_sp : 


0x05; 


// 


00000101 




cp 


%I, 


%SP 




map 


cp_ 


i_ 


_c : 


0x0 6; 


// 


00000110 




cp 


%I, 


%C 




map 


cp_ 


i_ 


_fl: 


0x0 7; 


// 


00000111 




cp 


%I, 


%FL 




map 


cp_ 


j. 


_i : 


0x08; 


// 


00001000 




cp 


%J, 


%I 




map 


nop : 




0x09; 


// 


00001001 




cp 


%J, 


%J 


= nop 


map 


cp_ 


j. 


_a : 


OxOA; 


// 


00001010 




cp 


%J, 


%A 




map 


cp_ 


j. 


_b: 


OxOB; 


// 


00001011 




cp 


%J, 


%B 




map 


cp_ 


j. 


_bp : 


OxOC; 


// 


00001100 




cp 


%J, 


%BP 




map 


cp_ 


j. 


_sp : 


OxOD; 


// 


00001101 




cp 


%J, 


%SP 




map 


cp_ 


j. 


_c : 


OxOE; 


// 


00001110 




cp 


%J, 


%C 




map 


cp_ 


j. 


_fl: 


OxOF; 


// 


00001111 




cp 


%J, 


%FL 





790 



Version "E" 



map 


cp_a_i : 


0x10; 


// 


00010000 




cp 


%A, 


%I 




map 


cp_a_j : 


0x11; 


// 


00010001 




cp 


%A, 


%J 




map 


nop : 


0x12; 


// 


00010010 


— 


cp 


%A, 


%A = 


nop 


map 


cp_a_b : 


0x13; 


// 


00010011 


— 


cp 


%A, 


%B 




map 


cp_a_bp : 


0x14; 


// 


00010100 


— 


cp 


%A, 


%BP 




map 


cp_a_sp : 


0x15; 


// 


00010101 


— 


cp 


%A, 


%SP 




map 


cp_a_c : 


0x16; 


// 


00010110 


— 


cp 


%A, 


%C 




map 


cp_a_f 1 : 


0x17; 


// 


00010111 


— 


cp 


%A, 


%FL 




map 


cp_b_i : 


0x18; 


// 


00011000 


= 


cp 


%B, 


%I 




map 


cp_b_j : 


0x19; 


// 


00011001 


— 


cp 


%B, 


%J 




map 


cp_b_a : 


OxlA; 


// 


00011010 


— 


cp 


%B, 


%A 




map 


nop : 


OxlB; 


// 


00011011 




cp 


%B, 


%B = 


nop 


map 


cp_b_bp : 


OxlC; 


// 


00011100 


= 


cp 


%B, 


%BP 




map 


cp_b_sp : 


OxlD; 


// 


00011101 




cp 


%B, 


%SP 




map 


cp_b_c : 


OxlE; 


// 


00011110 


= 


cp 


%B, 


%C 




map 


cp_b_f 1 : 


OxlF; 


// 


00011111 


— 


cp 


%B, 


%FL 




map 


cp_bp_i : 


0x20; 


// 


00100000 


= 


cp 


%BP 


,%I 




map 


cp_bp_ j : 


0x21; 


// 


00100001 


— 


cp 


%BP 


, %J 




map 


cp_bp_a : 


0x22; 


// 


00100010 


— 


cp 


%BP 


, %A 




map 


cp_bp_b : 


0x23; 


// 


00100011 




cp 


%BP 


, %B 




map 


nop : 


0x2 4; 


// 


00100100 


— 


cp 


%BP 


, %BP 


= nop 


map 


cp_bp_sp : 


0x25; 


// 


00100101 


= 


cp 


%BP 


, %SP 




map 


cp_bp_c : 


0x2 6; 


// 


00100110 


— 


cp 


%BP 


, %C 


= nop 


map 


cp_bp_f 1 : 


0x27; 


// 


00100111 


= 


cp 


%BP 


, %FL 




map 


cp_sp_i : 


0x28; 


// 


00101000 




cp 


%SP 


,%I 




map 


cp_sp_ j : 


0x29; 


// 


00101001 


— 


cp 


%SP 


, %J 




map 


cp_sp_a : 


0x2A; 


// 


00101010 


— 


cp 


%SP 


, %A 




map 


cp_sp_b : 


0x2B; 


// 


00101011 


= 


cp 


%SP 


, %B 




map 


cp_sp_bp : 


0x2C; 


// 


00101100 




cp 


%SP 


, %BP 




map 


nop : 


0x2D; 


// 


00101101 


— 


cp 


%SP 


, %SP 


= nop 


map 


cp_sp_c : 


0x2E; 


// 


00101110 


— 


cp 


%SP 


, %C 




map 


cp_sp_f 1 : 


0x2F; 


// 


00101111 


— 


cp 


%SP 


, %FL 




map 


cp_c_i : 


0x30; 


// 


00110000 


= 


cp 


%C, 


%I 




map 


cp_c_j : 


0x31; 


// 


00110001 


— 


cp 


%C, 


%J 




map 


cp_c_a : 


0x32; 


// 


00110010 


= 


cp 


%C, 


%A 




map 


cp_c_b : 


0x33; 


// 


00110011 


— 


cp 


%C, 


%B 




map 


cp_c_bp : 


0x34; 


// 


00110100 


— 


cp 


%C, 


%BP 




map 


cp_c_sp : 


0x35; 


// 


00110101 




cp 


%C, 


%SP 




map 


nop : 


0x36; 


// 


00110110 




cp 


%C, 


%C 


= nop 


map 


cp_c_f 1 : 


0x37; 


// 


00110111 




cp 


%C, 


%FL 





Version "E" 



791 



map 


cp_f l_i : 


0x38; 


// 


00111000 




cp 


%FL, %I 




map 


cp_f l_j : 


0x39; 


// 


00111001 




cp 


%FL, %J 




map 


cp_f l_a : 


0x3A; 


// 


00111010 




cp 


%FL, %A 




map 


cp_f l_b : 


0x3B; 


// 


00111011 


— 


cp 


%FL, %B 




map 


cp_f l_bp : 


0x3C; 


// 


00111100 


= 


cp 


%FL, %BP 




map 


cp_f l_sp : 


0x3D; 


// 


00111101 


— 


cp 


%FL, %SP 




map 


cp_f l_c : 


0x3E; 


// 


00111110 


— 


cp 


%FL, %C 




map 


nop : 


0x3F; 


// 


00111111 


= 


cp 


%FL, %FL = 


nop 


// 








010000. . 


— 


cp 


#,% 




map 


cp_num_i : 


0x40; 


// 


01000000 


= 


cp 


#, %I 




map 


cp_num_j : 


0x41; 


// 


01000001 


= 


cp 


#, %J 




map 


cp_num_a : 


0x42; 


// 


01000010 


— 


cp 


#, %A 




map 


cp_num_b : 


0x43; 


// 


01000011 


= 


cp 


#, %B 




// 








010001. . 




cp 


(%),% 




map 


cp_mi_a : 


0x44; 


// 


01000100 


— 


cp 


(%I) , %A 




map 


cp_mi_b : 


0x45; 


// 


01000101 




cp 


(%I) , %B 




map 


cp_m j_a : 


0x46; 


// 


01000110 


= 


cp 


(%J) , %A 




map 


cp_m j_b : 


0x47; 


// 


01000111 


— 


cp 


(%J) , %B 




// 








010010. . 


— 


cp 


%, %I 




map 


cp_a_mi : 


0x48; 


// 


01001000 


= 


cp 


%A, (%I) 




map 


cp_a_m j : 


0x4 9; 


// 


01001001 


— 


cp 


%A, (%J) 




map 


cp_b_mi : 


0x4A; 


// 


01001010 


= 


cp 


%B, (%I) 




map 


cp_b_m j : 


0x4B; 


// 


01001011 


= 


cp 


%B, (%J) 




// 








0100110. 


= 


cp 


#, (%) 




map 


cp_num_mi 


: 0x4C; 


// 


01001100 




cp 


#, (%D 




map 


cp_num_m j 


: 0x4D; 


// 


01001101 


— 


cp 


#, (%J) 




// 








0100111 . 


= 


cp 


(%) 




map 


cp_mi_mj : 


0x4E; 


// 


01001110 


= 


cp 


(%D 




map 


cp_m j_mi : 


0x4F; 


// 


01001111 




cp 


(%J) 




// 


















operands { 
















%1,%2 = { 


+0=0x00; 


+0 [5: 3] =%1; 


+ 0 [2 : 


0]=%2; }; 




#1,%2 = { 


+0=0x40; 


+0 [1 : 0] =%2; 


+1 


=#1[7:0]; +2= 


#1[15:8]; }; 




1) ,%2 = { 


+0=0x44; 


+0 [1 : 1] =%1; 


+ 0 [0 : 


0]=%2; }; 




%1, (%2) = { 


+0=0x48; 


+0 [1 : 1] =%1; 


+ 0 [0 : 


0]=%2; }; 




#1, (%2) = { 


+0=0x4C; 


+0 [0:0]=%2; 


+1 


=#1[7:0]; +2= 


#1[15:8]; }; 


}; 


1) = { 


+0=0x4E; 


+0 [0 :0]=%1; 


}; 








}; 

op cp8 { 

















792 



Version "E" 



// 










010100. . 


= cp8 


#, % 


map 


cp8 


_num_i : 


0x50; 


// 


01010000 


= cp8 


#, %I 


map 


cp8 


_num_ j : 


0x51; 


// 


01010001 


= cp8 


#, %J 


map 


cp8 


_num_a : 


0x52; 


// 


01010010 


= cp8 


#, %A 


map 


cp8 


_num_b : 


0x53; 


// 


01010011 


= cp8 


#, %B 


// 










010101. . 


= cp8 


(%),% 


map 


cp8 


_mi_a : 


0x54; 


// 


01010100 


= cp8 


(%I) , %A 


map 


cp8 


_mi_b : 


0x55; 


// 


01010101 


= cp8 


(%I) , %B 


map 


cp8 


_m j_a : 


0x5 6; 


// 


01010110 


= cp8 


(%J) , %A 


map 


cp8 


_m j_b : 


0x57; 


// 


01010111 


= cp8 


(%J) , %B 


// 










010110. . 


= cp8 


%, (%) 


map 


cp8 


_a_mi : 


0x58; 


// 


01011000 


= cp8 


%A, (%I) 


map 


cp8 


_a_mj : 


0x59; 


// 


01011001 


= cp8 


%A, (%J) 


map 


cp8 


_b_mi : 


0x5A; 


// 


01011010 


= cp8 


%B, (%I) 


map 


cp8 


_b_mj : 


0x5B; 


// 


01011011 


= cp8 


%B, (%J) 


// 










0101110. 


= cp8 


#, (%) 


map 


cp8 


_num_mi 


: 0x5C; 


// 


01011100 


= cp8 


#, (%D 


map 


cp8 


_num_m j 


: 0x5D; 


// 


01011101 


= cp8 


#, (%J) 


// 










0101111 . 


= cp8 


(%) 


map 


cp8 


_mi_m j : 


0x5E; 


// 


01011110 


= cp8 


(%I) 


map 


cp8 


_m j_mi : 


0x5F; 


// 


01011111 


= cp8 


(%J) 


// 
















operands { 












#1,%2 


= { 


+0=0x50; 


+ 0 


[1 : 0] =%2; 


+ 1=#1 


[7:0]; }; 


( 




%2 = { 


+0=0x54; 


+ 0 


[1 : 1] =%1; 


+ 0 [0 : 


0]=%2; }; 


%1, (% 


2) = { 


+0=0x58; 


+ 0 


[1 : 1] =%1; 


+ 0 [0 : 


0]=%2; }; 


#1, (% 


2) = { 


+0=0x5C; 


+ 0 


[0 : 0] =%2; 


+1=#1 


[7:0]; }; 


( 

}; 




= { 


+0=0x5E; 


+ 0 


[0 : 0] =%1; 


}; 




}; 
// 
















op push { 














// 










01100. . . 


= push 


% 


map 


push_i : 


0x60; 


// 


01100000 


= push 


%I 


map 


push_j : 


0x61; 


// 


01100001 


= push 


%J 


map 


push_a : 


0x62; 


// 


01100010 


= push 


%A 


map 


push_b : 


0x63; 


// 


01100011 


= push 


%B 


map 


push_bp : 


0x64; 


// 


01100100 


= push 


%BP 


map 


push_sp : 


0x65; 


// 


01100101 


= push 


%SP 


map 


push_c : 


0x66; 


// 


01100110 


= push 


%C 



Version "E" 



793 



map 


push 


_fl: 


0x67; 


// 


01100111 


— 


push %FL 


// 
















map 


push 


_num : 


0x80; 


// 


10000000 


— 


push # 


// 
















map 


push 


_mi : 


0x82; 


// 


10000010 


— 


push (%I) 


map 


push 


_mj : 


0x83; 


// 


10000011 


— 


push (%J) 


// 
















operands 


{ 












%1 




{ +o 


=0x60; +0 


[2 : 0 


]=%i; }; 






#1 




{ +o 


=0x80; +1 = 


= #1 [ 


7:0]; +2= 


#1 


[15:8]; }; 


(* 

}; 


1) = 


{ +o 


=0x82; +0 


[0:0 


]=%i; }; 






}; 

op pop { 














// 










OHIO. . . 


— 


pop % 


map 


pop_ 


i : 


0x70; 


// 


01110000 


— 


pop %I 


map 


pop_ 


j = 


0x71; 


// 


01110001 


= 


pop %J 


map 


pop_ 


a : 


0x72; 


// 


01110010 


— 


pop %A 


map 


pop_ 


b: 


0x7 3; 


// 


01110011 


— 


pop %B 


map 


pop_ 


op : 


0x7 4; 


// 


01110100 


= 


pop %BP 


map 


pop_ 


sp : 


0x7 5; 


// 


01110101 


— 


pop %SP 


map 


pop_ 


c : 


0x7 6; 


// 


01110110 


= 


pop %C 


map 


pop_ 


fl : 


0x7 7; 


// 


01110111 


= 


pop %FL 


// 










1000011. 


= 


pop (%) 


map 


pop_ 


mi : 


0x86; 


// 


10000110 




pop (%I) 


map 


pop_ 


mj : 


0x87; 


// 


10000111 


— 


pop (%J) 


// 
















operands 


{ 












%1 




{ +o 


=0x70; +0 


[2 : 0 


]=%i; }; 






(* 

}; 


1) = 


{ +o 


=0x86; +0 


[0:0 


]=%i; }; 






}; 
// 
















op push8 { 














// 










01101. . . 


— 


push8 % 


map 


push 


8_i: 


0x68; 


// 


01101000 


— 


push8 %I 


map 


push 


8_j: 


0x69; 


// 


01101001 


— 


push8 %J 


map 


push 


8_a: 


0x6A; 


// 


01101010 




push8 %A 


map 


push 


8_b: 


0x6B; 


// 


01101011 




push8 %B 


map 


push 


8_bp: 


0x6C; 


// 


01101100 




push 8 %BP 



794 



Version "E" 



map 


push? 


3_sp : 


0x6D; 


// 


01101101 


= 


push 8 %SP 






map 


push? 


3_c: 


0x6E; 


// 


01101110 


= 


push8 %C 






map 


push? 


3_fl : 


0x6F; 


// 


01101111 


— 


push 8 %FL 






// 




















map 


push? 


3_num : 


0x81; 


// 


10000001 


— 


push8 # 






// 










1000010. 


— 


push8 (%I) 






map 


push? 


3_mi : 


0x84; 


// 


10000100 


— 


push8 (%I) 






map 


push? 


3_mj : 


0x85; 


// 


10000101 


= 


push8 (%J) 






// 




















operands 


{ 
















%1 




{ +o= 


0x68; +0 


[2: 0 


]=%i; }; 










#1 




{ +0 = 


0x81; +1 


~1 : 0 


]=#i; }; 










(%D = 

}; 


{ +0 = 


0x81; +0 


;o : 0 


]=%i; }; 










}; 

op pop 


8 { 


















// 










01111 . . . 


— 


pop8 % 






map 


pop8_ 


_i : 


0x7 8; 


// 


01111000 


— 


pop8 %I 






map 


pop8_ 


_j : 


0x7 9; 


// 


01111001 


— 


pop8 %J 






map 


pop8_ 


_a : 


0x7A; 


// 


01111010 


— 


pop8 %A 






map 


pop8_ 


_b: 


0x7B; 


// 


01111011 


— 


pop8 %B 






map 


pop8_ 


_bp : 


0x7C; 


// 


01111100 


— 


pop8 %BP 






map 


pop8_ 


_sp : 


0x7D; 


// 


01111101 


= 


pop8 %SP 






map 


pop8_ 


_c : 


0x7E; 


// 


01111110 


= 


pop8 %C 






map 


pop8_ 


_fl: 


0x7F; 


// 


01111111 




pop8 %FL 






// 








// 


1000100. 


— 


pop8 (%) 






map 


pop8_ 


_mi : 


0x88; 


// 


10001000 


— 


pop8 (%I) 






map 


pop8_ 


_mj : 


0x89; 


// 


10001001 


= 


pop8 (%J) 






// 




















operands 


{ 
















%1 




{ +0 = 


0x78; +0 


[2: 0 


]=%i; }; 










}; 


1) = 


{ +o= 


0x88; +0 


;o : 0 


]=%i; }; 










}; 
// 




















op jump { 


















map 


jump_ 


_nc : 


0x90; 


// 


10010000 


= 


jump % carry 


0 


# 


map 


jump_ 


_c : 


0x91; 


// 


10010001 




jump % carry 


1 


# 


map 


jump_ 


_nz : 


0x92; 


// 


10010010 




jump %zero 


0 


# 


map 


jump_ 


_z : 


0x93; 


// 


10010011 




jump %zero 


1 


# 



Version "E" 



795 



map jump_nn: 


0x94; // 10010100 = 


jump %negative 


0 


# 


map jump_n: 


0x95; // 10010101 = 


jump %negative 


1 


# 


map jump_no: 


0x96; // 10010110 = 


jump %overflow 


0 


# 


map jump_o: 


0x97; // 10010111 = 


jump %overflow 


1 


# 


// 










map jump: 


OxFE; // 11111110 = 


jump # 






// 










operands { 










%1, #2, #3 


= { +0=0x90; +0 [2 :1]=%1; 


+ 0 [0:0]=#2; 








+1=#3[7:0]; +2=#3[15 


8]; }; 






#1 

}; 


= { +0 = 0xFE; +1 = #1 [7:0]; 


+2=#1[15:8]; }; 






}; 
// 










op equal { 










map equal: 


0x98; // 10011000 = 


equal 






operands { - 

}; 


= { +0=0x98; }; }; 








op not { 










map not : 


0x99; // 10011001 = 


not 






operands { - 


= { +0=0x99; }; }; 








}; 
// 










op and { 










map and: 


0x9A; // 10011010 = 


and 






operands { - 

}; 


= { +0=0x9A; }; }; 








op nand { 










map nand: 


0x9B; // 10011011 = 


nand 






operands { - 


= { +0=0x9B; }; }; 








}; 
// 










op or { 










map or : 


0x9C; // 10011100 = 


or 






operands { - 

}; 


= { +0=0x9C; }; }; 








op nor { 










map nor: 


0x9D; // 10011101 = 


nor 






operands { - 

}; 


= { +0=0x9D; }; }; 









796 



Version "E" 



// 












op xor { 












map xor: 




0x9E; // 


10011110 


= 


xor 


operands 

}; 


{ " 


- = { +0=0x9E; 


}; }; 






op nxor j 












map nxor 




0x9F; // 


10011111 


= 


nxor 


operands 


{ " 


- = { +0=0x9F; 


}; }; 






}; 
// 












op add { 












map add: 




OxAO; // 


10100000 


- 


add 


operands 


{ " 


- = { +0=0xA0; 


}; }; 






}; 

op sub { 












map sub: 




OxAl; // 


10100001 


= 


sub 


operands 


{ " 


- = { +0=0xAl; 


}; }; 






}; 
// 












op addc { 












map addc 




0xA2; // 


10100010 


= 


addc 


operands 


{ " 


- = { +0=0xA2; 


}; }; 






}; 

op subb { 












map subb 




0xA3; // 


10100011 


= 


subb 


operands 


{ " 


- = { +0=0xA3; 


}; }; 






}; 
// 












op lshl { 












map lshl 




0xA4; // 


10100100 


- 


lshl 


operands 

}; 


{ " 


- = { +0=0xA4; 


}; }; 






op lshr j 












map lshr 




0xA5; // 


10100101 


= 


lshr 


operands 


{ " 


- = { +0=0xA5; 


}; }; 






}; 
// 












op ashl { 












map ashl 




0xA6; // 


10100110 




ashl 


operands 


{ " 


- = { +0=0xA6; 


}; }; 







Version "E" 



797 



}; 

op ashr { 
map ashr: 
operands { - 


0xA7; // 
- = { +0=0xA7; 


10100111 

}; }; 




ashr 


}; 
// 

op rotcl { 
map rotcl: 
operands { - 

}; 


0xA8; // 
- = { +0=0xA8; 


10101000 

}; }; 




rotcl 


op rotcr { 
map rotcr: 
operands { - 


0xA9; // 
- = { +0=0xA9; 


10101001 

}; }; 




rotcr 


}; 
// 

op rotl { 
map rotl : 
operands { - 

}; 


OxAA; // 
- = { +0=0xAA; 


10101010 

}; }; 




rotl 


op rotr | 
map rotr: 
operands { - 


OxAB; // 
- = { +0=0xAB; 


10101011 

}; }; 




rotr 


}; 
// 

op add8 { 
map add8 : 
operands { - 


OxAC; // 
- = { +0=0xAC; 


10101100 

}; }; 




add8 


}; 

op sub8 { 
map sub8 : 
operands { - 


OxAD; // 
- = { +0=0xAD; 


10101101 

}; }; 




sub8 


}; 
// 

op add8c { 
map add8c: 
operands { - 

}; 


OxAE; // 
- = { +0=0xAE; 


10101110 

}; }; 




addc8 


op sub8b { 
map sub8b: 
operands { - 


OxAF; // 
- = { +0=0xAF; 


10101111 

}; }; 




subb8 



798 



Version "E" 



}; 
// 

op lsh81 { 
map lsh81: 
operands { - 

}; 


OxBO; // 
- = { +0=0xB0; 


10110000 

}; }; 




Ishl81 


op lsh8r { 
map lsh8r: 
operands { - 


OxBl; // 
- = { +0=0xBl; 


10110001 

}; }; 




lshl8r 


}; 
// 

op ash81 { 
map ash81: 
operands { - 

}; 


0xB2; // 
- = { +0=0xB2; 


10110010 

}; }; 




ashl81 


op ash8r { 
map ash8r: 
operands { - 


0xB3; // 
- = { +0=0xB3; 


10110011 

}; }; 




ashl8r 


}; 
// 

op rot8cl { 
map rot 8cl : 
operands { - 

}; 


0xB4; // 
- = { +0=0xB4; 


10110100 

}; }; 




rotc81 


op rot8cr { 
map rot8cr: 
operands { - 


0xB5; // 
- = { +0=0xB5; 


10110101 

}; }; 




rotc8r 


}; 
// 

op rot81 { 
map rot 81: 
operands { - 

}; 


0xB6; // 
- = { +0=0xB6; 


10110110 

}; }; 




rot 81 


op rot8r { 
map rot8r: 
operands { - 


0xB7; // 
- = { +0=0xB7; 


10110111 

}; }; 




rot8r 


}; 
// 

op cast { 
// 


// 


101110. . 




cast <sig>, % 



Version "E" 



799 



map cast_ 


_uns_ 




: 0xB8; // 


10111000 = 


cast 0 , %A 




map cast_ 


_uns_ 


b 


: 0xB9; // 


10111001 = 


cast 0, %B 




map cast_ 


_sig_ 


_a 


: OxBA; // 


10111010 = 


cast 1, %A 




map cast_ 


_sig_ 


b 


: OxBB; // 


10111011 = 


cast 1 , %B 




operands 


{ 












#1,%2 = 

}; 


{ + 0 


=0xB8; +0[1:1 


]=#1; +0[0: 


0]=%2; }; 




}; 
// 














op equals { 














map equals : 




OxBC; // 


10111100 = 


stack <= %A 




operands 

}; 


{ " 




{ +0=0xBC; 


}; }; 






op nots { 














map nots : 






OxBD; // 


10111101 = 


stack <= NOT %A 


operands 


{ " 




{ +0=0xBD; 


}; }; 






}; 
// 














op ands { 














map ands : 






OxBE; // 


10111110 = 


stack <= %A 


AND %B 


operands 

}; 


{ " 




{ +0=0xBE; 


}; }; 






op nands { 














map nands : 




OxBF; // 


10111111 = 


stack <= %A 


NAND %B 


operands 


{ " 




{ +0=0xBF; 


}; }; 






}; 
// 














op ors { 














map ors: 






OxCO; // 


11000000 = 


stack <= %A 


OR %B 


operands 

}; 


{ " 




{ +0=0xC0; 


}; }; 






op nors { 














map nors : 






OxCl; // 


11000001 = 


stack <= %A 


NOR %B 


operands 


{ " 




{ +0=0xCl; 


}; }; 






}; 
// 














op xors { 














map xors : 






0xC2; // 


11000010 = 


stack <= %A 


XOR %B 


operands 

}; 


{ " 




{ +0=0xC2; 


}; }; 







800 



Version "E" 



op nxors j 
map nxors : 
operands { - 


- = { 


0xC3; // 
+0=0xC3; 


11000011 

}; }; 




stack 


<= 


%A NXOR 


%B 


}; 
// 

op adds { 
map adds : 
operands { - 

}; 


- = { 


0xC4; // 
+0=0xC4 ; 


11000100 

}; }; 




stack 


<= 


%A + 


%B 




op subs { 
map subs : 
operands { - 


- = { 


0xC5; // 
+0=0xC5; 


11000101 

}; }; 




stack 


<= 


%A ~ 


%B 




}; 
// 

op addcs { 
map addcs: 
operands { - 

}; 


- = { 


0xC6; // 
+0=0xC6; 


11000110 

}; }; 




stack 


<= 


%A + 


%B 


+ % carry 


op subbs { 
map subbs: 
operands { - 


- = { 


0xC7; // 
+0=0xC7; 


11000111 

}; }; 




stack 


<= 


%A - 


%B 


- % carry 


}; 
// 

op lshls { 
map lshls : 
operands { - 

}; 


- = { 


0xC8; // 
+0=0xC8; 


11001000 

}; }; 




stack 


<= 


lshl 






op lshrs j 
map lshrs : 
operands { - 


- = { 


0xC9; // 
+0=0xC9; 


11001001 

}; }; 




stack 


<= 


lshr 






}; 
// 

op ashls { 
map ashls : 
operands { - 

}; 


- = { 


OxCA; // 
+0=0xCA; 


11001010 

}; }; 




stack 


<= 


ashl 






op ashrs { 
map ashrs : 
operands { - 

}; 


- = { 


OxCB; // 
+0=0xCB; 


11001011 

}; }; 




stack 


<= 


ashr 







Version "E" 



801 



// 

op rotcls { 
map rotcls : 
operands { - 

}; 


" = { 


OxCC; // 
+0=0xCC; 


11001100 

}; }; 




stack <= rotcl 


op rotcrs { 
map rotcrs : 
operands { - 


" = { 


OxCD; // 
+0=0xCD; 


11001101 

}; }; 




stack <= rotcr 


}; 
// 

op rotls { 
map rotls : 
operands { - 

}; 


" = { 


OxCE; // 
+0=0xCE; 


11001110 

}; }; 




stack <= rotl 


op rotrs { 
map rotrs : 
operands { - 


" = { 


OxCF; // 
+0=0xCF; 


11001111 

}; }; 




stack <= rotr 


}; 
// 

op add8s { 
map add8s: 
operands { - 


" = { 


OxDO; // 
+0=0xD0; 


11010000 

}; }; 




stack8 <= + 


}; 

op sub8s { 
map sub8s: 
operands { - 


" = { 


OxDl; // 
+0=0xDl; 


11010001 

}; }; 




stack 8 <= - 


}; 
// 

op add8cs { 
map add8cs : 
operands { - 

}; 


" = { 


0xD2; // 
+0=0xD2; 


11010010 

}; }; 




stack8 <= + + %carry 


op sub8bs { 
map sub8bs : 
operands { - 


" = { 


0xD3; // 
+0=0xD3; 


11010011 

}; }; 




stack8 <= - - %carry 


}; 
// 

op lsh81s { 
map lsh8 Is : 
operands { - 


" = { 


0xD4; // 
+0=0xD4; 


11010100 

}; }; 




stack8 <= lsh8r 



802 



Version "E" 



}; 

op lsh8rs { 
map lsh8rs : 
operands { - = 


0xD5; // 
{ +0=0xD5; 


11010101 

}; }; 




stack8 <= 


lsh8r 


}; 
// 

op ash81s { 
map ash8 Is : 
operands { - = 

}; 


0xD6; // 
{ +0=0xD6; 


11010110 

}; }; 




stack8 <= 


ash81 


op ash8rs { 
map ash8rs : 
operands { - = 


0xD7; // 
{ +0=0xD7; 


11010111 

}; }; 




stack8 <= 


ash8r 


}; 
// 

op rot8cls { 
map rot8cls: 
operands { - = 

}; 


0xD8; // 
{ +0=0xD8; 


11011000 

}; }; 




stack8 <= 


rot8cl 


op rot8crs { 
map rot 8crs : 
operands { - = 


0xD9; // 
{ +0=0xD9; 


11011001 

}; }; 




stack8 <= 


rot8cr 


}; 
// 

op rot81s { 
map rot81s : 
operands { - = 

}; 


OxDA; // 
{ +0=0xDA; 


11011010 

}; }; 




stack8 <= 


rot 81 


op rot8rs { 
map rot 8rs : 
operands { - = 


OxDB; // 
{ +0=0xDB; 


11011011 

}; }; 




stack8 <= 


rot8r 


// 

op casts { 

// // 1101110. 

map casts_uns: OxDC; // 11011100 
map casts_sig: OxDD; // 11011101 
operands { 

#1 = {+0=0xDC; +0[0:0]=#1; }; 

}; 


= 


casts <sig> 
casts 0 
casts 1 



Version "E" 



803 



}; 
// 








op call { 








map call : 




OxDE; // 11011110 


= call # 


map call_ 


_i : 


OxFC; // 11111100 


= call (%I) 


map call_ 


-j : 


OxFD; // 11111101 


= call (%J) 


operands 


{ 






#1 


{ 


+0=0xDE; +1=#1[7:0]; +2= 


#1[15:8]; }; 


(%D = 

}; 


{ 


+0=0xFC; +0[0:0]=%1; }; 




}; 

op return { 








map return: 


OxDF; // 11011111 


= return 


operands 


{ 


- = { +0=0xDF; }; }; 




}; 
// 








op int { 








map int : 




OxEO; // 11100000 


= int <n> 


operands 


{ 






#1 = { 

}; 


+0 


=0xE0; +1=#1; }; 




}; 

op iret { 








map iret : 




OxEl; // 11100001 


= iret 


operands 


{ 


- = { +0=0xEl; }; }; 




}; 
// 








op imrl { 








map imrl : 




0xE2; // 11100010 


= IMR load 


operands 


{ 






#1 


{ 


+0=0xE2; +1=#1[7:0]; }; 




}; 

operands 

}; 


{ 


- = { +0=0xE2; }; }; 




op ivtl { 








map ivtl : 




0xE3; // 11100011 


= IVT load 


operands 


{ 






#1 

}; 

}; 


{ 


+0=0xE3; +1=#1[7:0]; +2= 


#1[15:8]; }; 



804 



Version "E" 



// 










op flag_i { 










map flag_i_clr: 0xE4; 


// 11100100 




flag_i 0 


map flag_i_set: 0xE5; 


// 11100101 


= 


flag_± 1 


operands { 










#1 = { +0=0xE4; +0 [0 

}; 


:0]=#1; }; 






}; 
// 










op flag_c { 










map flag_c_clr: 0xE6; 


// 11100110 




flag_c 0 


map flag_c_set: 0xE7; 


// 11100111 


= 


flag_c 1 


operands { 










#1 = { +0=0xE6; +0 [0 

}; 


:0]=#1; }; 






}; 
// 










op in { 










map in_num_a : 0xE8 




// 11101000 


= 


in <n>, %A 


map in_num_b: 0xE9 




// 11101001 




in <n>, %B 


map in_num_mi : OxEA 




// 11101010 


— 


in <n>, (%I) 


map in_num_m j : OxEB 




// 11101011 




in <n>, (%J) 


operands { 










#1,%2 = { +0=0xE8; 


+ 0 [0 : 0] =%2; 


+1 


=#i; }; 


#1, (%2) = { +0=0xEA; 

}; 


+0 [0 : 0] =%2; 


+1 


=#i; }; 


}; 

op out { 










map out_a_num: OxEC 




// 11101100 


= 


out %A, # 


map out_b_num: OxED 




// 11101101 


= 


out %B,# 


map out_mi_num: OxEE 




// 11101110 


— 


out 


map out_mi_num: OxEF 




// 11101111 




out (%J) , # 


operands { 










%1,#2 = { +0=0xEC; 


+ 0 [0 : 0] =%1; 


+1 


=#2; }; 


(%1) , #2 = { +0=0xEE; 

}; 


+0 [0 : 0] =%1; 


+1 


=#2; }; 


}; 
// 










op ifack_jump { 










map ifack_jump: OxFO; 


// 11110000 




jump if ack from device 



Version "E" 



805 



operands { 

#1,#2 = { +0=0xF0; +1=#1; +2=#2[7:0]; +3=#2 [ 15 : 8 ] ; }; 

}; 

}; 

op ifack_call { 

map ifack_call: OxFl; // 11110001 = call if ack from device 

operands { 

#1,#2 = { +0=0xFl; +1=#1; +2=#2[7:0]; +3=#2[15:8]; }; 

}; 

}; 
// 

op cmpr { 

map cmpr: 0xF2; // 11110010 = compare %A, %B 

operands { - = { +0 [ 7 : 0 ] =0xF2 ; }; }; 

}; 

op testr { 

map testr: 0xF3; // 11110011 = test %A, %B 

operands { - = { +0 [ 7 : 0 ] =0xF3 ; }; }; 

}; 
// 

op cmpi { 

map cmpi: 0xF4; // 11110100 = compare (% I) , (%J) 

operands { - = { +0 [ 7 : 0 ] =0xF4 ; }; }; 

}; 

op testi { 

map testi: 0xF5; // 11110101 = test (%I) , (%J) 

operands { - = { +0 [ 7 : 0 ] =0xF5 ; }; }; 

}; 
// 

op cmps { 

map cmps: 0xF6; // 11110110 = compare stack 

operands { - = { +0 [ 7 : 0 ] =0xF6; }; }; 

}; 

op tests { 

map tests: 0xF7; // 11110111 = test stack 

operands { - = { +0 [ 7 : 0 ] =0xF7 ; }; }; 

}; 
// 

op cmp8i { 

map cmp8i: 0xF8; // 11111000 = compare8 (%I) , (%J) 



806 



Version "E" 



operands { - 

}; 


- = { +0[7 


0]=0xF8; }; } 


f 


op test8i { 
map test8i: 
operands { - 


0xF9; 
- = { +0[7 


// 11111001 

0]=0xF9; }; } 


= tests (%I), (%J) 

f 


}; 
// 

op cmp8s { 

-L -L L 

map cmp8s: 
operands { - 


OxFA; 
- = { +0[7 


// 11111010 

0]=0xFA; }; } 


= compare 8 stack 

f 


}; 

op test 8s { 
map test 8s : 
operands { - 


OxFB; 
- = { +0[7 


// 11111011 

0]=0xFB; }; } 


= tests stack 

f 


}; 
// 

op stop { 
map stop: 
operands { - 

}; 


OxFF; 
- = { +0[7 


// 11111111 

0]=0xFF; }; } 


f 



12.14 Microcode 

It follows the microcode listing, describing the opcode procedures. The microcode is 
much different from the previous version, because the bit fields have different names 
and because the memory is accessed in a new slower way. Please notice that the fetch 
cycle is started with just f etch=f 1, but it requires two clock cycles and a separate 
ctrl=load is also required. 

Listing 12.43. Microcode for TKGate. 

begin microcode @ 0 
// 

fetchl : 

// MAR <= PC++, MIR <= RAM == fetch=fl; 

mar=p mar=rank8 mar=load pc=dpl mir=ram_read; 
fetchO : 

// MIR <= RAM, MPC <= MIR 

ctrl=load; 

// 

nop : 



Version "E" 



807 



// MPC <= # fetch 






addr=fetchl jump=true; 






// 






cp_i_j : 






fetch=fl j=a j=load i=a 


i=bw; 


// J <= I 


ctrl=load; 






cp_i_a : 






fetch=fl a=a a=load i=a 


i=bw; 


// A <= I 


ctrl=load; 






cp_i_b : 






fetch=fl b=a b=load i=a 


i=bw; 


// B <= I 


ctrl=load; 






cp_i_sp : 






fetch=fl sp=a sp=load i= 


a i=bw; 


// SP <= I 


ctrl=load; 






cp_i_bp : 






fetch=fl bp=a bp=load i= 


a i=bw; 


// BP <= I 


ctrl=load; 






cp_i_c : 






fetch=fl c=a c=load i=a 


i=bw; 


// C <= I 


ctrl=load; 






cp_i_f 1 : 






fetch=fl fl=a fl=load i= 


a i=bw; 


// FL <= I 


ctrl=load; 






cp_j_i : 






fetch=fl i=a i=load j=a 


j=bw; 


// I <= J 


ctrl=load; 






cp_j_a : 






fetch=fl a=a a=load j=a 


j=bw; 


// A <= J 


ctrl=load; 






cp_ j_b : 






fetch=fl b=a b=load j=a 


j=bw; 


// B <= J 


ctrl=load; 






cp_j_sp : 






fetch=fl sp=a sp=load j= 


a j=bw; 


// SP <= J 


ctrl=load; 






cp_ j_bp : 






fetch=fl bp=a bp=load j= 


a j =bw ; 


// BP <= J 


ctrl=load; 






cp_j_c : 






fetch=fl c=a c=load j=a 


j=bw; 


// C <= J 


ctrl=load; 






cp_j_f 1 : 







808 



Version "E" 



fetch=fl fl=a fl=load j 


=a j=bw; 


// FL <= J 


ctrl=load; 






cp_a_i : 






fetch=fl i=a i=load a=a 


a=bw; 


// I <= A 


ctrl=load; 






cp_a_j : 






fetch=fl j=a j=load a=a 


a=bw; 


// J <= A 


ctrl=load; 






cp_a_b : 






fetch=fl b=a b=load a=a 


a=bw; 


// B <= A 


ctrl=load; 






cp_a_sp : 






fetch=fl sp=a sp=load a 


=a a=bw; 


// SP <= A 


ctrl=load; 






cp_a_bp : 






fetch=fl bp=a bp=load a 


=a a=bw; 


// BP <= A 


ctrl=load; 






cp_a_c : 






fetch=fl c=a c=load a=a 


a=bw; 


// C <= A 


ctrl=load; 






cp_a_f 1 : 






fetch=fl fl=a fl=load a 


=a a=bw; 


// FL <= A 


ctrl=load; 






cp_b_i : 






fetch=fl i=a i=load b=a 


b=bw; 


// I <= B 


ctrl=load; 






cp_b_j : 






fetch=fl j=a j=load b=a 


b=bw; 


// J <= B 


ctrl=load; 






cp_b_a : 






fetch=fl a=a a=load b=a 


b=bw; 


// A <= B 


ctrl=load; 






cp_b_sp : 






fetch=fl sp=a sp=load b 


=a b=bw; 


// SP <= B 


ctrl=load; 






cp_b_bp : 






fetch=fl bp=a bp=load b 


=a b=bw; 


// BP <= B 


ctrl=load; 






cp_b_c : 






fetch=fl c=a c=load b=a 


b=bw; 


// C <= B 


ctrl=load; 






cp_b_f 1 : 






fetch=fl fl=a fl=load b 


=a b=bw; 


// FL <= B 



Version "E" 



809 



ctrl=load; 






cp_sp_i : 






fetch=fl i=a i=load sp=a 


sp=bw; 


// I <= SP 


ctrl=load; 






cp_sp_ j : 






fetch=fl j=a j=load sp=a 


sp=bw; 


// J <= SP 


ctrl=load; 






cp_sp_a : 






fetch=fl a=a a=load sp=a 


sp=bw; 


// A <= SP 


ctrl=load; 






cp_sp_b : 






fetch=fl b=a b=load sp=a 


sp=bw; 


// B <= SP 


ctrl=load; 






cp_sp_bp : 






fetch=fl bp=a bp=load sp 


=a sp=bw; 


// BP <= SP 


ctrl=load; 






cp_sp_c : 






fetch=fl c=a c=load sp=a 


sp=bw; 


// C <= SP 


ctrl=load; 






cp_sp_f 1 : 






fetch=fl fl=a fl=load sp 


=a sp=bw; 


// FL <= SP 


ctrl=load; 






cp_bp_i : 






fetch=fl i=a i=load bp=a 


bp=bw; 


// I <= BP 


ctrl=load; 






cp_bp_ j : 






fetch=fl j=a j=load bp=a 


bp=bw; 


// J <= BP 


ctrl=load; 






cp_bp_a : 






fetch=fl a=a a=load bp=a 


bp=bw; 


// A <= BP 


ctrl=load; 






cp_bp_b : 






fetch=fl b=a b=load bp=a 


bp=bw; 


// B <= BP 


ctrl=load; 






cp_bp_sp : 






fetch=fl sp=a sp=load bp 


=a bp=bw; 


// SP <= BP 


ctrl=load; 






cp_bp_c : 






fetch=fl c=a c=load bp=a 


bp=bw; 


// C <= BP 


ctrl=load; 






cp_bp_f 1 : 






fetch=fl fl=a fl=load bp 


=a bp=bw; 


// FL <= BP 


ctrl=load; 







810 



Version "E" 



cp_c_i : 




fetch=fl i=a i=load c=a c=bw; 


// I <= C 


ctrl=load; 




cp_c_j : 




fetch=fl j=a j=load c=a c=bw; 


// J <= C 


ctrl=load; 




cp_c_a : 




fetch=fl a=a a=load c=a c=bw; 


// A <= C 


ctrl=load; 




cp_c_b : 




fetch=fl b=a b=load c=a c=bw; 


// B <= C 


ctrl=load; 




cp_c_sp : 




fetch=fl sp=a sp=load c=a c=bw; 


// SP <= C 


ctrl=load; 




cp_c_bp : 




fetch=fl bp=a bp=load c=a c=bw; 


// BP <= C 


ctrl=load; 




cp_c_f 1 : 




fetch=fl fl=a fl=load c=a c=bw; 


// FL <= C 


ctrl=load; 




cp_f l_i : 




fetch=fl i=a i=load fl=a fl=bw; 


// I <= FL 


ctrl=load; 




cp_f 1_ j : 




fetch=fl j=a j=load fl=a fl=bw; 


// J <= FL 


ctrl=load; 




cp_f l_a : 




fetch=fl a=a a=load fl=a fl=bw; 


// A <= FL 


ctrl=load; 




cp_f l_b : 




fetch=fl b=a b=load fl=a fl=bw; 


// B <= FL 


ctrl=load; 




cp_f l_sp : 




fetch=fl sp=a sp=load fl=a fl=bw; 


// SP <= FL 


ctrl=load; 




cp_f l_bp : 




fetch=fl bp=a bp=load fl=a fl=bw; 


// BP <= FL 


ctrl=load; 




cp_f l_c : 




fetch=fl c=a c=load fl=a fl=bw; 


// C <= FL 


ctrl=load; 




cp_num_i : 





Version "E" 



811 





// MAR <= PC+=2, MDR <= RAM (3 clocks) ; 








mar=p mar=rankl6 mar=load pc=dp2 mdr=ram_read; ctrl=nop 


; Ctrl 


=nop; 




// I <= MDR; 








fetch=fl i=a i=load mdr=a mdr=rankl6 mdr=bw; 








ctrl=load; 






cp. 


_num_j : 








// MAR <= PC+=2, MDR <= RAM (3 clocks); 








mar=p mar=rankl6 mar=load pc=dp2 mdr=ram_read; ctrl=nop 


; Ctrl 


=nop; 




// J <= MDR; 








fetch=fl j=a j=load mdr=a mdr=rankl6 mdr=bw; 








ctrl=load; 






cp. 


_num_a : 








// MAR <= PC+=2, MDR <= RAM (3 clocks); 








mar=p mar=rankl6 mar=load pc=dp2 mdr=ram_read; ctrl=nop 


; Ctrl 


=nop; 




// A <= MDR; 








fetch=fl a=a a=load mdr=a mdr=rankl6 mdr=bw; 








ctrl=load; 






cp. 


_num_b : 








// WAR <= PC+=2, MDR <= RAM (3 clocks); 








mar=p mar=rankl6 mar=load pc=dp2 mdr=ram_read; ctrl=nop 


; Ctrl 


=nop; 




// B <= MDR; 








fetch=fl b=a b=load mdr=a mdr=rankl6 mdr=bw; 








ctrl=load; 






cp. 


_mi_a : 








// WAR <= I, MDR <= RAM (3 clocks) ; 








mar=i mar=rankl6 mar=load mdr=ram_read; ctrl=nop; ctrl= 


nop; 






// A <= MDR; 








fetch=fl a=a a=load mdr=a mdr=rankl6 mdr=bw; 








ctrl=load; 






cp. 


_mi_b : 








// WAR <= I, MDR <= RAM (3 clocks); 








mar=i mar=rankl6 mar=load mdr=ram_read; ctrl=nop; ctrl= 


nop; 






// B <= MDR; 








fetch=fl b=a b=load mdr=a mdr=rankl6 mdr=bw; 








ctrl=load; 






cp. 


_m j_a : 








// WAR <= J, MDR <= RAM (3 clocks); 








mar=j mar=rankl6 mar=load mdr=ram_read; ctrl=nop; ctrl= 


nop; 






// A <= MDR; 








fetch=fl a=a a=load mdr=a mdr=rankl6 mdr=bw; 








ctrl=load; 






cp. 


_m j_b : 








// WAR <= J, MDR <= RAM (3 clocks) ; 







812 



Version "E" 





mar=j mar=rankl6 mar=load mdr=ram_read; 


ctrl=nop; 


ctrl=nop; 






// B <= MDR; 










fetch=fl b=a b=load mdr=a mdr=rankl6 mdr 


=bw; 








ctrl=load; 








cp. 


_a_mi : 










// MDR <= A 










mdr=a mdr=load a=bw; 










// MAR <= I, RAM <= MDR (3 clocks) 










mar=i mar=rankl6 mar=load mar=ram_write; 


ctrl=nop; 


ctrl=nop; 






fetch=fl; ctrl=load; 








cp. 


_a_m j : 










// MDR <= A 










mdr=a mdr=load a=bw; 










// MAR <= J, RAM <= MDR (3 clocks) 










mar=j mar=rankl6 mar=load mar=ram_write; 


ctrl=nop; 


ctrl=nop; 






fetch=fl; ctrl=load; 








cp. 


_b_mi : 










// MDR <= B 










mdr=a mdr=load b=bw; 










// MAR <= I, RAM <= MDR (3 clocks) 










mar=i mar=rankl 6 mar=load mar=ram_write; 


ctrl=nop; 


ctrl=nop; 






fetch=fl; ctrl=load; 








cp. 


_b_m j : 










// MDR <= B 










mdr=a mdr=load b=bw; 










// MAR <= J, RAM <= MDR (3 clocks) 










mar=j mar=rankl6 mar=load mar=ram_write; 


ctrl=nop; 


ctrl=nop; 






fetch=fl; ctrl=load; 








cp. 


_num_mi : 










// MAR <= PC+=2, MDR <= RAM (3 clocks); 










mar=p mar=rankl6 mar=load pc=dp2 mdr=ram 


_read; ctrl=nop; Ctrl 


=nop; 




// WAR <= I, RAM <= MDR (3 clocks) 










mar=i mar=rankl6 mar=load mar=ram_write; 


ctrl=nop; 


ctrl=nop; 






fetch=fl; ctrl=load; 








cp. 


_num_mj : 










// WAR <= PC+-2, MDR <= RAM (3 clocks) ; 










mar=p mar=rankl6 mar=load pc=dp2 mdr=ram 


_read; ctrl=nop; Ctrl 


=nop; 




// WAR <= J, RAM <= MDR (3 clocks) 










mar=j mar=rankl6 mar=load mar=ram_write; 


ctrl=nop; 


ctrl=nop; 






fetch=fl; ctrl=load; 








cp. 


_mi_mj : 










// WAR <= I, MDR <= RAM (3 clocks) ; 










mar=i mar=rankl6 mar=load mdr=ram_read; 


ctrl=nop; 


ctrl=nop; 





Version "E" 



813 





// MAR <= J, RAM <= 


MDR (3 clocks) 








mar=j mar=rankl6 mar=load mar=ram_write; ctrl=nop; 


Ctrl 


=nop; 




fetch=fl; ctrl=load; 








cp. 


_m j_mi : 










// MAR <= J, MDR <= 


RAM (3 clocks); 








mar=j mar=rankl6 mar 


=load mdr=ram_read; ctrl=nop; 


ctrl= 


nop; 




// MAR <= I, RAM <= 


MDR (3 clocks) 








mar=i mar=rankl6 mar=load mar=ram_write; ctrl=nop; 


Ctrl 


=nop; 




fetch=fl; ctrl=load; 








cp 


3_num_i : 










// MAR <= PC++, MDR 


<- RAM (2 clocks) ; 








mar=p mar=rank8 mar= 


load pc=dpl mdr=ram_read; Ctrl 


=nop; 






// J <= MDR; 










fetch=fl i=a i=load 


mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 








cp 


3_num_j : 










// MAR <= PC++, MDR 


<= RAM (2 clocks) ; 








mar=p mar=rank8 mar= 


load pc=dpl mdr=ram_read; Ctrl 


=nop; 






// J <= MDR; 










fetch=fl j=a j=load 


mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 








cp 


3_num_a : 










// MAR <= PC++, MDR 


<= RAM (2 clocks); 








mar=p mar=rank8 mar= 


load pc=dpl mdr=ram_read; Ctrl 


=nop; 






// A <= MDR; 










fetch=fl a=a a=load 


mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 








cp 


3_num_b : 










// MAR <= PC++, MDR 


<= RAM (2 clocks); 








mar=p mar=rank8 mar= 


load pc=dpl mdr=ram_read; Ctrl 


=nop; 






// B <= MDR; 










fetch=fl b=a a=load 


mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 








cp 


3_mi_a : 










// WAR <= I, MDR <= 


RAM (2 clocks); 








mar=i mar=rank8 mar= 


load mdr=ram_read; ctrl=nop; 








// A <= MDR; 










fetch=fl a=a a=load 


mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 








cp 


3_mi_b : 










// MAR <= I, MDR <= 


RAM (2 clocks); 








mar=i mar=rank8 mar= 


load mdr=ram_read; ctrl=nop; 








// B <= MDR; 









814 



Version "E" 





fetch=fl b=a a=load 


mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 










1_m j_a : 










// MAR <= J, MDR <= 


RAM (2 clocks) ; 








mar=j mar=rank8 mar= 


load mdr=ram_read; ctrl=nop; 








// A <= MDR; 










fetch=fl a=a a=load 


mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 








cp£ 


}_m j_b : 










// MAR <= J, MDR <= 


RAM (2 clocks) ; 








mar=j mar=rank8 mar= 


load mdr=ram_read; ctrl=nop; 








// B <= MDR; 










fetch=fl b=a a=load 


mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 








cp£ 


3_a_mi : 










// MDR <= A 










mdr=a mdr=load a=bw; 










// MAR <= I, RAM <= 


MDR (3 clocks) 








mar=i mar=rank8 mar= 


load mar=ram_write ; ctrl=nop; 


ctrl = 


nop; 




fetch=fl; ctrl=load; 








cp£ 


3_a_mj : 










// MDR <= A 










mdr=a mdr=load a=bw; 










// MAR <= J, RAM <= 


MDR (3 clocks) 








mar=j mar=rank8 mar= 


load mar=ram_write ; ctrl=nop; 


ctrl = 


nop; 




fetch=fl; ctrl=load; 








cpi 


3_b_mi : 










// MDR <= B 










mdr=a mdr=load b=bw; 










// MAR <= I, RAM <= 


MDR (3 clocks) 








mar=i mar=rank8 mar= 


load mar=ram_write ; ctrl=nop; 


ctrl = 


nop; 




fetch=fl; ctrl=load; 








cp£ 


3_b_mj : 










// MDR <= A 










mdr=a mdr=load b=bw; 










// MAR <= J, RAM <= 


MDR (3 clocks) 








mar=j mar=rank8 mar= 


load mar=ram_write ; ctrl=nop; 


ctrl = 


nop; 




fetch=fl; ctrl=load; 








cp£ 


3_num_mi : 










// MAR <= PC++, MDR 


<= RAM (2 clocks); 








mar=p mar=rank8 mar= 


load pc=dp2 mdr=ram_read; Ctrl 


=nop; 






// MAR <= I, RAM <= 


MDR (2 clocks) 








mar=i mar=rank8 mar= 


load mar=ram_write ; ctrl=nop; 







Version "E" 



815 



fetch=f 1; 


ctrl=load; 














cp8_num_mj : 
















// MAR <= 


PC++, MDR <= RAM (2 clocks) ; 














mar=p mar= 


=rank8 mar=load pc=dp2 mdr=ram 


_read; Ctrl 


=nop; 










// MAR <= 


J, RAM <= MDR (2 clocks) 














mar=j mar= 


=rank8 mar=load mar=ram_write; 


ctrl=nop; 












fetch=f 1; 


ctrl=load; 














cp8_mi_mj : 
















// WAR <= 


I, MDR <= RAM (2 clocks) ; 














mar=i mar= 


=rank8 mar=load mdr=ram_read; 


ctrl=nop; 












// MAR <= 


J, RAM <= MDR (2 clocks) 














mar=j mar= 


=rank8 mar=load mar=ram_write; 


ctrl=nop; 












fetch=f 1; 


ctrl=load; 














cp8_mj_mi : 
















// MAR <= 


J, MDR <= RAM (2 clocks); 














mar=j mar= 


=rank8 mar=load mdr=ram_read; 


ctrl=nop; 












// MAR <= 


I, RAM <= MDR (2 clocks) 














mar=i mar= 


=rank8 mar=load mar=ram_write; 


ctrl=nop; 












fetch=f 1; 


ctrl=load; 














push_i : 
















// MDR <= 


I 














mdr=a mdr= 


=load i=a i=bw; 














// MAR <= 


SP--2, RAM <= MDR (3 clocks) 














mar=s mar= 


=rankl6 mar=load mar=ram_write 


sp=qm2 sp= 


qup; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 














push_j : 
















// MDR <= 


J 














mdr=a mdr= 


= load j=a j=bw; 














// MAR <= 


SP=-2, RAM <= MDR (3 clocks) 














mar=s mar= 


=rankl6 mar=load mar=ram_write 


sp=qm2 sp= 


qup; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 














push_a : 
















// MDR <= 


A 














mdr=a mdr= 


=load a=a a=bw; 














// MAR <= 


SP=-2, RAM <= MDR (3 clocks) 














mar=s mar= 


=rankl6 mar=load mar=ram_write 


sp=qm2 sp= 


qup; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 














push_b : 
















// MDR <= 


B 














mdr=a mdr= 


= load b=a b=bw; 














// MAR <= 


SP=-2, RAM <= MDR (3 clocks) 














mar=s mar= 


=rankl6 mar=load mar=ram_write 


sp=qm2 sp= 


qup; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 















816 



Version "E" 



push_bp : 


















// WDR <= 


BP 
















mdr=a mdr= 


load bp=a bp=bw; 
















// MAR <= 


SP--2, RAM <= MDR (3 clocks) 
















mar=s mar= 


=rankl6 mar=load mar=ram_write 


sp=qm2 


sp 


=qup; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 
















push_sp : 


















// MDR <= 


SP 
















mdr=a mdr= 


load sp=a sp=bw; 
















// MAR <= 


SP--2, RAM <= MDR (3 clocks) 
















mar=s mar= 


•rankl6 mar=load mar=ram_write 


sp=qm2 


sp 


=qup ; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 
















push_c : 


















// MDR <= 


C 
















mdr=a mdr= 


load c=a c=bw; 
















// MAR <= 


SP--2, RAM <= MDR (3 clocks) 
















mar=s mar= 


•rankl6 mar=load mar=ram_write 


sp=qm2 


sp 


=qup ; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 
















push_f 1 : 


















// MDR <= 


FL 
















mdr=a mdr= 


; load fl=a fl=bw; 
















// MAR <= 


SP--2, RAM <= MDR (3 clocks) 
















mar=s mar= 


•rankl6 mar=load mar=ram_write 


sp=qm2 


sp 


=qup ; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 
















push_num: 


















// MAR <= 


PC++, MDR <= RAM (3 clocks) ; 
















mar=p mar= 


=rankl6 mar=load pc=dp2 mdr=ram_read; 


ctrl=nop 


; ctrl=nop 


; 




// MAR <= 


SP--2, RAM <= MDR (3 clocks) 
















mar=s mar= 


•rankl6 mar=load mar=ram_write 


sp=qm2 


sp 


=qup ; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 
















push_mi : 


















// WAR <= 


I, MDR <= RAM (3 clocks) ; 
















mar=i mar= 


=rankl6 mar=load mdr=ram_read; 


ctrl=nop; 


ctrl = 


nop; 








// WAR <= 


SP=-2, RAM <= MDR (3 clocks) 
















mar=s mar= 


=rankl6 mar=load mar=ram_write 


sp=qm2 


sp 


=qup; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 
















push_m j : 


















// WAR <= 


J, MDR <= RAM (3 clocks); 
















mar=j mar= 


=rankl6 mar=load mdr=ram_read; 


ctrl=nop; 


ctrl = 


nop; 








// WAR <= 


SP=-2, RAM <= MDR (3 clocks) 
















mar=s mar= 


=rankl6 mar=load mar=ram_write 


sp=qm2 


sp 


=qup ; 


Ctrl 


=nop; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 
















pop_i : 



















Version "E" 



817 





// MAR <= SP=+2, MDR <= RAM (3 clocks); 












mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


Ctrl 


=nop; 


Ctrl 


=nop; 




// I <= MDR; 












fetch=fl i=a i=load mdr=a mdr=rankl6 mdr=bw; 












ctrl=load; 










pop. 


_j : 

// MAR <= SP=+2, MDR <= RAM (3 clocks); 












mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


Ctrl 


=nop; 


Ctrl 


=nop; 




// J <= MDR; 












fetch=fl j=a j=load mdr=a mdr=rankl6 mdr=bw; 












ctrl=load; 










pop. 


_a : 

// MAR <= SP=+2, MDR <= RAM (3 clocks); 












mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


Ctrl 


=nop; 


Ctrl 


=nop; 




// A <= MDR; 












fetch=fl a=a a=load mdr=a mdr=rankl6 mdr=bw; 












ctrl=load; 










pop. 


_b: 

// MAR <= SP-+2, MDR <= RAM (3 clocks); 












mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


Ctrl 


=nop; 


Ctrl 


=nop; 




// B <= MDR; 












fetch=fl b=a b=load mdr=a mdr=rankl6 mdr=bw; 












ctrl=load; 










pop. 


_bp : 

// MAR <= SP-+2, MDR <= RAM (3 clocks) ; 












mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


Ctrl 


=nop; 


Ctrl 


=nop; 




// BP <= MDR; 












fetch=fl bp=a bp=load mdr=a mdr=rankl6 mdr=bw; 












ctrl=load; 










pop. 


_sp : 

// MAR <= SP=+2, MDR <= RAM (3 clocks); 












mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


Ctrl 


=nop; 


Ctrl 


=nop; 




// SP <= MDR; 












fetch=fl sp=a sp=load mdr=a mdr=rankl6 mdr=bw; 












ctrl=load; 










pop. 


_c : 

// MAR <= SP=+2, MDR <= RAM (3 clocks); 












mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


Ctrl 


=nop; 


Ctrl 


=nop; 




// C <= MDR; 












fetch=fl c=a c=load mdr=a mdr=rankl6 mdr=bw; 












ctrl=load; 










pop. 


_fl : 

// MAR <= SP=+2, MDR <= RAM (3 clocks); 











818 



Version "E" 



mar=s mar=rankl6 mar=load mdr=ram_read 


sp=dp2 ; 


ctrl=nop; ctrl=nop; 


// FL <= MDR; 






fetch=fl fl=a fl=load mdr=a mdr=rankl6 


mdr=bw; 




ctrl=load; 






pop_mi : 






// MAR <= SP=+2, MDR <= RAM (3 clocks) ; 






mar=s mar=rankl6 mar=load mdr=ram_read 


sp=dp2 ; 


ctrl=nop; ctrl=nop; 


// MAR <= I, RAM <= MDR (3 clocks) 






mar=i mar=rankl6 mar=load mar=ram_write 


; ctrl= 


nop; ctrl=nop; 


fetch=fl; ctrl=load; 






pop_mj : 






// MAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read 


sp=dp2 ; 


ctrl=nop; ctrl=nop; 


// MAR <= J, RAM <= MDR (3 clocks) 






mar=j mar=rankl6 mar=load mar=ram_write 


; ctrl= 


nop; ctrl=nop; 


fetch=fl; ctrl=load; 






push8_i : 






// MDR <= I 






mdr=a mdr=load i=a i=bw; 






// MAR <= — SP, RAM <= MDR (2 clocks) 






mar=s mar=rank8 mar=load mar=ram_write 


sp=qml 


sp=qup; ctrl=nop; 


fetch=fl; ctrl=load; 






push8_j : 






// MDR <= J 






mdr=a mdr=load j=a j=bw; 






// MAR <= — SP, RAM <= MDR (2 clocks) 






mar=s mar=rank8 mar=load mar=ram_write 


sp=qml 


sp=qup; ctrl=nop; 


fetch=fl; ctrl=load; 






push8_a : 






// MDR <= A 






mdr=a mdr=load a=a a=bw; 






// MSP <= — SP, RAM <= MDR (2 clocks) 






mar=s mar=rank8 mar=load mar=ram_write 


sp=qml 


sp=qup; ctrl=nop; 


fetch=fl; ctrl=load; 






push8_b : 






// MDP <= B 






mdr=a mdr=load b=a b=bw; 






// MAP <= — SP, RAM <= MDR (2 clocks) 






mar=s mar=rank8 mar=load mar=ram_write 


sp=qml 


sp=qup; ctrl=nop; 


fetch=fl; ctrl=load; 






push8_bp : 






// MDP <= BP 






mdr=a mdr=load bp=a bp=bw; 







Version "E" 



819 



// MAR <= 


— SP, RAM 


<- MDR (2 clocks) 










mar=s mar= 


rank8 mar= 


load mar=ram_write 


sp=qml 


sp=qup; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 












push8_sp : 














// MDR <= 


SP 












mdr=a mdr= 


load sp=a 


sp=bw; 










// MAR <= 


— SP, RAM 


<- MDR (2 clocks) 










mar=s mar= 


rank8 mar= 


load mar=ram_write 


sp=qml 


sp=qup; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 












push8_c : 














// MDR <= 


C 












mdr=a mdr= 


load c=a c 


=bw; 










// MAR <= 


— SP, RAM 


<- MDR (2 clocks) 










mar=s mar= 


=rank8 mar= 


load mar=ram_write 


sp=qml 


sp=qup; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 












push8_f 1 : 














// MDR <= 


FL 












mdr=a mdr= 


load fl=a 


f l=bw; 










// WAR <= 


— SP, RAM 


<= MDR (2 clocks) 










mar=s mar= 


=rank8 mar= 


load mar=ram_write 


sp=qml 


sp=qup; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 












push8_num : 














// MAR <= 


PC++, MDR 


<- RAM (2 clocks) ; 










mar=p mar= 


rank8 mar= 


load pc=dpl mdr=ram_read; 


ctrl=nop 


; 




// WAR <= 


— SP, RAM 


<= MDR (2 clocks) 










mar=s mar= 


=rank8 mar= 


load mar=ram_write 


sp=qml 


sp=qup; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 












push8_mi : 














// WAR <= 


I, MDR <= 


RAW (2 clocks); 










mar=i mar= 


=rank8 mar= 


load mdr=ram_read; 


ctrl=nop; 






// WAR <= 


— SP, RAM 


<= MDR (2 clocks) 










mar=s mar= 


rank8 mar= 


load mar=ram_write 


sp=qml 


sp=qup; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 












push8_mj : 














// WAR <= 


J, MDR <= 


RAW (2 clocks); 










mar=j mar= 


=rank8 mar= 


load mdr=ram_read; 


ctrl=nop; 






// WAR <= 


— SP, RAM 


<- MDR (2 clocks) 










mar=s mar= 


rank8 mar= 


load mar=ram_write 


sp=qml 


sp=qup; 


Ctrl 


=nop; 


fetch=f 1; 


ctrl=load; 












pop8_i : 














// WAR <= 


SP++, MDR 


<- RAM (2 clocks) ; 










mar=s mar= 


rank8 mar= 


load mdr=ram_read 


sp=dpl ; 


ctrl=nop 


; 




// J <= MDR; 













820 



Version "E" 





fetch=fl i=a i=load mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 






pop! 


3_j: 








// MAR <= SP++, MDR <= RAM (2 clocks); 








mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 




// J <= MDR; 








fetch=fl j=a j=load mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 






pop! 


3_a: 








// MAR <= SP++, MDR <= RAM (2 clocks) ; 








mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 




// A <= MDR; 








fetch=fl a=a a=load mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 






pop! 


3_b: 








// MAR <= SP++, MDR <= RAM (2 clocks) ; 








mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 




// B <= MDR; 








fetch=fl b=a b=load mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 






pop! 


3_bp : 








// MAR <= SP++, MDR <= RAM (2 clocks); 








mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 




// BP <= MDR; 








fetch=fl bp=a bp=load mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 






pop! 


3_sp : 








// MAR <= SP++, MDR <= RAM (2 clocks); 








mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 




// SP <= MDR; 








fetch=fl sp=a sp=load mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 






pop! 


3_c: 








// MAR <= SP++, MDR <= RAM (2 clocks); 








mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 




// C <= MDR; 








fetch=fl c=a c=load mdr=a mdr=rank8u mdr=bw; 








ctrl=load; 






pop! 


3_fl: 








// MAR <= SP++, MDR <= RAM (2 clocks) ; 








mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 




// FL <= MDR; 








fetch=fl fl=a fl=load mdr=a mdr=rank8u mdr=bw; 







Version "E" 



821 



ctrl=load; 
pop8_mi : 

// MAR <= SP++, MDR <= RAM (2 clocks); 

mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; ctrl=nop; 
// MAR <= I, RAM <= MDR (2 clocks) 

mar=i mar=rank8 mar=load mar=ram_write; ctrl=nop; 
fetch=fl; ctrl=load; 
pop8_m j : 

// MAR <= SP++, MDR <= RAM (2 clocks) ; 

mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; ctrl=nop; 
// MAR <= J, RAM <= MDR (2 clocks) 

mar=j mar=rank8 mar=load mar=ram_write; ctrl=nop; 
fetch=fl; ctrl=load; 
jump : 

// WAR <= PC+=2, MDR <= RAM (3 clocks); 

mar=p mar=rankl6 mar=load pc=dp2 mdr=ram_read; ctrl=nop; ctrl=nop; 
// PC <= MDR; 

pc=a pc=load mdr=a mdr=rankl6 mdr=bw; 
fetch=fl; ctrl=load; 
jump_nc : 

// check flag before reading the destination argument 

addr=jump jump=carry_f ; 

// discard destination address: ++PC and fetch 

pc=qp2 pc=qup fetch=fl; 
ctrl=load; 
j ump_c : 

// check flag before reading the destination argument 

addr=jump jump=carry_t ; 

// discard destination address: ++PC and fetch 

pc=qp2 pc=qup fetch=fl; 
ctrl=load; 
j ump_n z : 

// check flag before reading the destination argument 

addr=jump jump=zero_f; 

// discard destination address: ++PC and fetch 

pc=qp2 pc=qup fetch=fl; 
ctrl=load; 
jump_z : 

// check flag before reading the destination argument 

addr=jump jump=zero_t; 

// discard destination address: ++PC and fetch 

pc=qp2 pc=qup fetch=fl; 
ctrl=load; 



822 



Version "E" 



jump_nn : 




// check flag before reading the destination argument 




addr=jump jump=negative_f ; 




// discard destination address: ++PC and fetch 




pc=qp2 pc=qup fetch=fl; 




ctrl=load; 




j ump_n : 




// check flag before reading the destination argument 




addr=jump jump=negative_t ; 




// discard destination address: ++PC and fetch 




pc=qp2 pc=qup fetch=fl; 




ctrl=load; 




jump_no : 




// check flag before reading the destination argument 




addr=jump jump=overf low_f ; 




// discard destination address: ++PC and fetch 




pc=qp2 pc=qup fetch=fl; 




ctrl=load; 




j ump_o : 




// check flag before reading the destination argument 




addr=jump jump=overf low_t ; 




// discard destination address: ++PC and fetch 




pc=qp2 pc=qup fetch=fl; 




ctrl=load; 




equal : 




// C <= A (FL updated) 




fetch=fl c=b c=load fl=b fl=load alu=a alu=rankl6 a=a a=bw; 




ctrl=load; 




not : 




// C <= ~A (FL updated) 




fetch=fl c=b c=load fl=b fl=load alu=not alu=rankl6 a=a a=bw; 




ctrl=load; 




and : 




// C <= A&B (FL updated) 




fetch=fl c=b c=load fl=b fl=load alu=and alu=rankl6 a=a a=bw b=l 


3 b=bw; 


ctrl=load; 




nand: 




// C <= ~(A&B) (FL updated) 




fetch=fl c=b c=load fl=b fl=load alu=nand alu=rankl6 a=a a=bw b= 


=b b=bw; 


ctrl=load; 




or : 




// C <= A/S (FL updated) 




fetch=fl c=b c=load fl=b fl=load alu=or alu=rankl6 a=a a=bw b=b 


b=bw; 



Version "E" 



823 



ctrl=load; 
















nor : 
















// C <= ~(AIB) (FL updated) 
















fetch=fl c=b c=load fl=b fl=load 


alu= 


nor 


alu= 


rankl 6 


a=a 


a=bw b=b 


b=bw; 


ctrl=load; 
















xor : 
















// C <= A A B (FL updated) 
















fetch=fl c=b c=load fl=b fl=load 


alu= 


xor 


alu= 


rankl 6 


a=a 


a=bw b=b 


b=bw; 


ctrl=load; 
















nxor : 
















// C <= ~(A*B) (FL updated) 
















fetch=fl c=b c=load fl=b fl=load 


alu= 


nxor 


alu 


=rankl 6 


a=a 


a=bw b=b 


b=bw; 


ctrl=load; 
















add : 
















// C <= A+B (FL updated) 
















fetch=fl c=b c=load fl=b fl=load 


alu= 


add 


alu= 


rankl 6 


a=a 


a=bw b=b 


b=bw; 


ctrl=load; 
















sub : 
















// C <= A-B (FL updated) 
















fetch=fl c=b c=load fl=b fl=load 


alu= 


sub 


alu= 


rankl 6 


a=a 


a=bw b=b 


b=bw; 


ctrl=load; 
















addc : 
















// C <= A+B+carry (FL updated) 
















fetch=fl c=b c=load fl=b fl=load 


alu= 


addc 


alu 


=rankl 6 


a=a 


a=bw b=b 


b=bw; 


ctrl=load; 
















subb : 
















// C <= A-B-borrow (FL updated) 
















fetch=fl c=b c=load fl=b fl=load 


alu= 


subb 


alu 


=rankl 6 


a=a 


a=bw b=b 


b=bw; 


ctrl=load; 
















lshl: 
















// C <= lshl (A) (FL updated) 
















fetch=fl c=b c=load fl=b fl=load 


alu= 


lshl 


alu 


=rankl 6 


a=a 


a=bw; 




ctrl=load; 
















lshr : 
















// C <= lshr (A) (FL updated) 
















fetch=fl c=b c=load fl=b fl=load 


alu= 


■lshr 


alu 


=rankl 6 


a=a 


a=bw; 




ctrl=load; 
















ashl : 
















// C <= ashl (A) (FL updated) 
















fetch=fl c=b c=load fl=b fl=load 


alu= 


■ashl 


alu 


=rankl 6 


a=a 


a=bw; 




ctrl=load; 
















ashr : 
















// C <= ashr (A) (FL updated) 

















824 



Version "E" 



fetch=fl c=b c=load fl=b fl=load alu= 


=ashr 


alu=rankl 6 


a=a a=bw; 




ctrl=load; 










rotcl : 










// C <= rotcl (A) (FL updated) 










fetch=fl c=b c=load fl=b fl=load alu= 


=rotcl 


alu=rankl 6 


a=a a=bw; 




ctrl=load; 










rotcr : 










// C <= rotcr (A) (FL updated) 










fetch=fl c=b c=load fl=b fl=load alu= 


=rotcr 


alu=rankl 6 


a=a a=bw; 




ctrl=load; 










rotl : 










// C <= rotl (A) (FL updated) 










fetch=fl c=b c=load fl=b fl=load alu= 


=rotl 


alu=rankl 6 


a=a a=bw; 




ctrl=load; 










rotr : 










// C <= rotr (A) (FL updated) 










fetch=fl c=b c=load fl=b fl=load alu= 


: rotr 


alu=rankl 6 


a=a a=bw; 




ctrl=load; 










add8 : 










// C <= A[7:0]+B[7:0] (FL updated) 










fetch=fl c=b c=load fl=b fl=load alu= 


=add8 


alu=rank8u 


a=a a=bw b=b b 


=bw; 


ctrl=load; 










sub8 : 










// C <= A[7:0]+B[7:0] (FL updated) 










fetch=fl c=b c=load fl=b fl=load alu= 


= sub8 


alu=rank8u 


a=a a=bw b=b b 


=bw; 


ctrl=load; 










add8c : 










// C <= A[7:0]+B[7:0] (FL updated) 










fetch=fl c=b c=load fl=b fl=load alu= 


=add8c 


alu=rank8u 


a=a a=bw b=b 


b=bw; 


ctrl=load; 










sub8b : 










// C <= A[7:0]+B[7:0] (FL updated) 










fetch=fl c=b c=load fl=b fl=load alu= 


=sub8b 


alu=rank8u 


a=a a=bw b=b 


b=bw; 


ctrl=load; 










lsh81: 










// C <= A[7:0]+B[7:0] (FL updated) 










fetch=fl c=b c=load fl=b fl=load alu= 


=lsh81 


alu=rank8u 


a=a a=bw; 




ctrl=load; 










lsh8r : 










// C <= A[7:0]+B[7:0] (FL updated) 










fetch=fl c=b c=load fl=b fl=load alu= 


= lsh8r 


alu=rank8u 


a=a a=bw; 




ctrl=load; 










ash81 : 











Version "E" 



825 



// C <= A[7:0]+B[7:0] (FL updated) 






fetch=fl c=b c=load fl=b fl=load alu=ash81 alu=rank8u a 


=a a 


=bw; 


ctrl=load; 






ash8r : 






// C <= A[7:0]+B[7:0] (FL updated) 






fetch=fl c=b c=load fl=b fl=load alu=ash8r alu=rank8u a 


=a a 


=bw; 


ctrl=load; 






rot8cl : 






// C <= A[7:0]+B[7:0] (FL updated) 






fetch=fl c=b c=load fl=b fl=load alu=rot8cl alu=rank8u 


a=a 


a=bw ; 


ctrl=load; 






rot8cr : 






// C <= A[7:0]+B[7:0] (FL updated) 






fetch=fl c=b c=load fl=b fl=load alu=rot8cr alu=rank8u 


a=a 


a=bw ; 


ctrl=load; 






rot81: 






// C <= A[7:0]+B[7:0] (FL updated) 






fetch=fl c=b c=load fl=b fl=load alu=rot81 alu=rank8u a 


=a a 


=bw; 


ctrl=load; 






rot8r : 






// C <= A[7:0]+B[7:0] (FL updated) 






fetch=fl c=b c=load fl=b fl=load alu=rot8r alu=rank8u a 


=a a 


=bw; 


ctrl=load; 






cast_uns_a : 






c=b c=load fl=b fl=load alu=a alu=rank8u a=a a=bw; 






fetch=fl a=a a=load c=a c=bw 






ctrl=load; 






cast_uns_b : 






c=b c=load fl=b fl=load alu=a alu=rank8u b=a b=bw; 






fetch=fl b=a b=load c=a c=bw 






ctrl=load; 






cast_sig_a : 






c=b c=load fl=b fl=load alu=a alu=rank8s a=a a=bw; 






fetch=fl a=a a=load c=a c=bw 






ctrl=load; 






cast_sig_b : 






c=b c=load fl=b fl=load alu=a alu=rank8s b=a b=bw; 






fetch=fl b=a b=load c=a c=bw 






ctrl=load; 






equals : 






// MAR <= SP, MDR <= RAM (3 clocks) ; 






mar=s mar=rankl6 mar=load mdr=ram_read; ctrl=nop; ctrl= 


nop; 




// C <= MDR (FL updated) 







826 



Version "E" 



c=b c=load fl=b fl=load alu=a alu=rankl6 mdr=a 


mdr=rankl6 mdr=bw; 




fetch=fl; ctrl=load; 






nots : 






// MAR <= SP-+2, MDR <= RAM (3 clocks) ; 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// C <= ~MDR (FL updated) 






c=b c=load fl=b fl=load alu=not alu=rankl6 mdr 


=a mdr=rankl6 mdr=bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP--2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 






ands : 






// MAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// A <= MDR; 






a=a a=load mdr=a mdr=rankl6 mdr=bw; 






// MAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// B <= MDR; 






b=a b=load mdr=a mdr=rankl6 mdr=bw; 






// C <= A&B (FL updated) 






c=b c=load fl=b fl=load alu=and alu=rankl6 a=a 


a=bw b=b b=bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP--2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 






nands : 






// MAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// A <= MDR; 






a=a a=load mdr=a mdr=rankl6 mdr=bw; 






// WAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// B <= MDR; 






b=a b=load mdr=a mdr=rankl6 mdr=bw; 






// C <= ~(A&B) (FL updated) 






c=b c=load fl=b fl=load alu=nand alu=rankl6 a= 


a a=bw b=b b=bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP--2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 



Version "E" 



827 



fetch=fl; ctrl=load; 










ors : 










// WAR <= SP=+2, MDR <= RAM (3 clocks) ; 










mar=s mar=rankl6 mar=load mdr=ram_read sp= 


dp2; 


ctrl=nop; 


ctrl=nop; 




// A <= MDR; 










a=a a=load mdr=a mdr=rankl6 mdr=bw; 










// MAR <= SP-+2, MDR <= RAM (3 clocks) ; 










mar=s mar=rankl6 mar=load mdr=ram_read sp= 


dp2; 


ctrl=nop; 


ctrl=nop; 




// B <= MDR; 










b=a b=load mdr=a mdr=rankl6 mdr=bw; 










// C <= A/B (FL updated) 










c=b c=load fl=b fl=load alu=or alu=rankl6 


a=a 


a=bw b=b b 


=bw; 




// MDR <= C 










mdr=a mdr=load c=a c=bw; 










// MAR <= SP=-2, RAM <= MDR (3 clocks) 










mar=s mar=rankl6 mar=load mar=ram_write sp 


=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 










nors : 










// MAR <= SP-+2, MDR <= RAM (3 clocks) ; 










mar=s mar=rankl6 mar=load mdr=ram_read sp= 


dp2; 


ctrl=nop; 


ctrl=nop; 




// A <= MDR; 










a=a a=load mdr=a mdr=rankl6 mdr=bw; 










// MAR <= SP-+2, MDR <= RAM (3 clocks) ; 










mar=s mar=rankl6 mar=load mdr=ram_read sp= 


dp2; 


ctrl=nop; 


ctrl=nop; 




// B <= MDR; 










b=a b=load mdr=a mdr=rankl6 mdr=bw; 










// C <= ~(A\B) (FL updated) 










c=b c=load fl=b fl=load alu=nor alu=rankl6 


a=a 


a=bw b=b 


b=bw; 




// MDR <= C 










mdr=a mdr=load c=a c=bw; 










// MAR <= SP=-2, RAM <= MDR (3 clocks) 










mar=s mar=rankl6 mar=load mar=ram_write sp 


=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 










xor s : 










// MAR <= SP=+2, MDR <= RAM (3 clocks); 










mar=s mar=rankl6 mar=load mdr=ram_read sp= 


dp2 ; 


ctrl=nop; 


ctrl=nop; 




// A <= MDR; 










a=a a=load mdr=a mdr=rankl6 mdr=bw; 










// MAR <= SP-+2, MDR <= RAM (3 clocks) ; 










mar=s mar=rankl6 mar=load mdr=ram_read sp= 


dp2 ; 


ctrl=nop; 


ctrl=nop; 




// B <= MDR; 










b=a b=load mdr=a mdr=rankl6 mdr=bw; 










// C <= A A B (FL updated) 











828 



Version "E" 



c=b c=load fl=b fl=load alu=xor alu=rankl6 a=a 


a=bw b=b b=bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP=-2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 






nxors : 






// MAR <= SP-+2, MDR <= RAM (3 clocks) ; 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// A <= MDR; 






a=a a=load mdr=a mdr=rankl6 mdr=bw; 






// MAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// B <= MDR; 






b=a b=load mdr=a mdr=rankl6 mdr=bw; 






// C <= ~(A*B) (FL updated) 






c=b c=load fl=b fl=load alu=nxor alu=rankl6 a= 


a a=bw b=b b=bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP=-2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 






adds : 






// MAR <= SP-+2, MDR <= RAM (3 clocks) ; 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// A <= MDR; 






a=a a=load mdr=a mdr=rankl6 mdr=bw; 






// WAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// B <= MDR; 






b=a b=load mdr=a mdr=rankl6 mdr=bw; 






// C <= A+B (FL updated) 






c=b c=load fl=b fl=load alu=add alu=rankl6 a=a 


a=bw b=b b=bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP=-2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 






subs : 






// MAR <= SP-+2, MDR <= RAM (3 clocks) ; 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// A <= MDR; 






a=a a=load mdr=a mdr=rankl6 mdr=bw; 







Version "E" 



829 



// MAR <= SP=+2, MDR <= RAM (3 clocks) ; 








mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop 


; ctrl=nop; 




// B <= MDR; 








b=a b=load mdr=a mdr=rankl6 mdr=bw; 








// C <= A-B (FL updated) 








c=b c=load fl=b fl=load alu=sub alu=rankl6 a=a 


a=bw b=b 


b=bw; 




// MDR <= C 








mdr=a mdr=load c=a c=bw; 








// MAR <= SP=-2, RAM <= MDR (3 clocks) 








mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; 


ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 








addcs : 








// MAR <= SP=+2, MDR <= RAM (3 clocks); 








mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop 


; ctrl=nop; 




// A <= MDR; 








a=a a=load mdr=a mdr=rankl6 mdr=bw; 








// MAR <= SP=+2, MDR <= RAM (3 clocks); 








mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop 


; ctrl=nop; 




// B <= MDR; 








b=a b=load mdr=a mdr=rankl6 mdr=bw; 








// C <= A+B+carry (FL updated) 








c=b c=load fl=b fl=load alu=addc alu=rankl6 a= 


a a=bw b= 


b b=bw; 




// MDR <= C 








mdr=a mdr=load c=a c=bw; 








// MAR <= SP=-2, RAM <= MDR (3 clocks) 








mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; 


ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 








subbs : 








// MAR <= SP=+2, MDR <= RAM (3 clocks); 








mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop 


; ctrl=nop; 




// A <= MDR; 








a=a a=load mdr=a mdr=rankl6 mdr=bw; 








// MAR <= SP=+2, MDR <= RAM (3 clocks); 








mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop 


; ctrl=nop; 




// B <= MDR; 








b=a b=load mdr=a mdr=rankl6 mdr=bw; 








// C <= A-B-borrow (FL updated) 








c=b c=load fl=b fl=load alu=subb alu=rankl6 a= 


a a=bw b= 


b b=bw; 




// MDR <= C 








mdr=a mdr=load c=a c=bw; 








// MAR <= SP--2, RAM <= MDR (3 clocks) 








mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; 


ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 









830 



Version "E" 



lshls : 






// WAR <= SP-+2, MDR <= RAM (3 clocks) ; 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// C <= Ishl (A) (FL updated) 






c=b c=load fl=b fl=load alu=lshl alu=rankl6 mdr 


=a mdr=rankl6 mdr=bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP--2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 






lshrs : 






// WAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// C <= lshr(A) (FL updated) 






c=b c=load fl=b fl=load alu=lshr alu=rankl6 mdr 


=a mdr=rankl6 mdr=bw; 




// WDR <= C 






mdr=a mdr=load c=a c=bw; 






// WAR <= SP--2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 






ashls : 






// WAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// C <= ashl (A) (FL updated) 






c=b c=load fl=b fl=load alu=ashl alu=rankl6 mdr 


=a mdr=rankl6 mdr=bw; 




// WDR <= C 






mdr=a mdr=load c=a c=bw; 






// WAR <= SP=-2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 






ashrs : 






// WAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 




// C <= ashr(A) (FL updated) 






c=b c=load fl=b fl=load alu=ashr alu=rankl6 mdr 


=a mdr=rankl6 mdr=bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// WAR <= SP=-2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 


sp=qup; ctrl=nop; Ctrl 


=nop; 


fetch=fl; ctrl=load; 






rotcls : 






// WAR <= SP-+2, MDR <= RAM (3 clocks) ; 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; 


ctrl=nop; ctrl=nop; 





Version "E" 



831 



// C <= rotcl (A) (FL updated) 






c=b c=load fl=b fl=load alu=rotcl alu=rankl6 mdr=a mdr=rankl6 mdr 


=bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP=-2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; 


Ctrl 


=nop; 


fetch=fl; ctrl=load; 






rotcrs : 






// WAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; ctrl=nop; ctrl=nop 


r 




// C <= rotcr(A) (FL updated) 






c=b c=load fl=b fl=load alu=rotcr alu=rankl6 mdr=a mdr=rankl6 mdr 


=bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP=-2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; 


Ctrl 


=nop; 


fetch=fl; ctrl=load; 






rotls : 






// MAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; ctrl=nop; ctrl=nop 


r 




// C <= rotl (A) (FL updated) 






c=b c=load fl=b fl=load alu=rotl alu=rankl6 mdr=a mdr=rankl6 mdr= 


bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP=-2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; 


Ctrl 


=nop; 


fetch=fl; ctrl=load; 






rotrs : 






// MAR <= SP=+2, MDR <= RAM (3 clocks); 






mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; ctrl=nop; ctrl=nop 


r 




// C <= rotr(A) (FL updated) 






c=b c=load fl=b fl=load alu=rotr alu=rankl6 mdr=a mdr=rankl6 mdr= 


bw; 




// MDR <= C 






mdr=a mdr=load c=a c=bw; 






// MAR <= SP=-2, RAM <= MDR (3 clocks) 






mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; 


Ctrl 


=nop; 


fetch=fl; ctrl=load; 






add8s : 






// MAR <= ++SP, MDR <= RAM (2 clocks) ; 






mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; ctrl=nop; 






// A <= MDR; 






a=a a=load mdr=a mdr=rankl6 mdr=bw; 






// MAR <= ++SP, MDR <= RAM (2 clocks); 







832 



Version "E" 





mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 








// B <= MDR; 












b=a b=load mdr=a mdr=rank8u mdr=bw; 












// C <= A+B (FL updated) 












c=b c=load fl=b fl=load alu=add8 alu=rank8u a= 


a a= 


bw b= 


b b= 


bw; 




// MDR <= C 












mdr=a mdr=load c=a c=bw; 












// MAR <= — SP, RAM <= MDR (2 clocks) 












mar=s mar=rankl6 mar=load mar=ram_write sp=qml 


sp= 


qup; 


Ctrl 


=nop; 




fetch=fl; ctrl=load; 










sub? 


3s : 












// MAR <= ++SP, MDR <= RAM (2 clocks) ; 












mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 








// A <= MDR; 












a=a a=load mdr=a mdr=rankl6 mdr=bw; 












// MAR <= ++SP, MDR <= RAM (2 clocks) } 












mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 








// B <= MDR; 












b=a b=load mdr=a mdr=rank8u mdr=bw; 












// C <= A-B (FL updated) 












c=b c=load fl=b fl=load alu=sub8 alu=rank8u a= 


a a= 


bw b= 


b b= 


bw; 




// MDR <= C 












mdr=a mdr=load c=a c=bw; 












// MAR <= — SP, RAM <= MDR (2 clocks) 












mar=s mar=rankl6 mar=load mar=ram_write sp=qml 


sp= 


qup; 


Ctrl 


=nop; 




fetch=fl; ctrl=load; 










addS 


3cs : 












// MAR <= ++SP, MDR <= RAM (2 clocks); 












mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 








// A <= MDR; 












a=a a=load mdr=a mdr=rankl6 mdr=bw; 












// MAR <= ++SP, MDR <= RAM (2 clocks) ; 












mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; 


Ctrl 


=nop; 








// B <= MDR; 












b=a b=load mdr=a mdr=rank8u mdr=bw; 












// C <= A+B+carry (FL updated) 












c=b c=load fl=b fl=load alu=add8c alu=rank8u a 


=a a 


=bw b 


=b b 


=bw; 




// MDR <= C 












mdr=a mdr=load c=a c=bw; 












// MAR <= — SP, RAM <= MDR (2 clocks) 












mar=s mar=rankl6 mar=load mar=ram_write sp=qml 


sp= 


qup; 


Ctrl 


=nop; 




fetch=fl; ctrl=load; 










subi 


3bs : 











Version "E" 



833 



// MAR <= ++SP, MDR <= RAM (2 clocks) ; 

mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; ctrl=nop; 
// A <= MDR; 

a=a a=load mdr=a mdr=rankl6 mdr=bw; 
// MAR <= ++SP, MDR <= RAM (2 clocks); 

mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; ctrl=nop; 
// B <= MDR; 

b=a b=load mdr=a mdr=rank8u mdr=bw; 
// C <= A-B-borrow (FL updated) 

c=b c=load fl=b fl=load alu=sub8b alu=rank8u a=a a=bw b=b b=bw; 
// MDR <= C 

mdr=a mdr=load c=a c=bw; 

// MAR <= — SP, RAM <= MDR (2 clocks) 

mar=s mar=rankl6 mar=load mar=ram_write sp=qml sp=qup; ctrl=nop; 
fetch=fl; ctrl=load; 
lsh81s : 

// MAR <= ++SP, MDR <= RAM (2 clocks) ; 

mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; ctrl=nop; 
// C <= lsh81 (A) (FL updated) 

c=b c=load fl=b fl=load alu=lsh81 alu=rank8u mdr=a mdr=rank8u mdr=bw; 
// MDR <= C 

mdr=a mdr=load c=a c=bw; 

// MAR <= — SP, RAM <= MDR (2 clocks) 

mar=s mar=rank8 mar=load mar=ram_write sp=qml sp=qup; ctrl=nop; 
fetch=fl; ctrl=load; 
lsh8rs : 

// MAR <= ++SP, MDR <= RAM (2 clocks); 

mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; ctrl=nop; 
// C <= lsh8r(A) (FL updated) 

c=b c=load fl=b fl=load alu=lsh8r alu=rank8u mdr=a mdr=rank8u mdr=bw; 
// MDR <= C 

mdr=a mdr=load c=a c=bw; 

// MAR <= — SP, RAM <= MDR (2 clocks) 

mar=s mar=rank8 mar=load mar=ram_write sp=qml sp=qup; ctrl=nop; 
fetch=fl; ctrl=load; 
ash81s : 

// MAR <= ++SP, MDR <= RAM (2 clocks); 

mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; ctrl=nop; 
// C <= ash81 (A) (FL updated) 

c=b c=load fl=b fl=load alu=ash81 alu=rank8u mdr=a mdr=rank8u mdr=bw; 
// MDR <= C 

mdr=a mdr=load c=a c=bw; 

// MAR <= — SP, RAM <= MDR (2 clocks) 



834 



Version "E" 





mar=s mar=rank8 mar=load mar=ram_write 


sp=qml 


sp=qup; ctrl=nop; 




fetch=fl; ctrl=load; 






ash! 


Brs : 








// WAR <= ++SP, MDR <= RAM (2 clocks); 








mar=s mar=rank8 mar=load mdr=ram_read 


sp=dpl ; 


ctrl=nop; 




// C <= ash8r(A) (FL updated) 








c=b c=load fl=b fl=load alu=ash8r alu= 


rank8u 


mdr=a mdr=rank8u mdr=bw; 




// MDR <= C 








mdr=a mdr=load c=a c=bw; 








// MAR <= — SP, RAM <= MDR (2 clocks) 








mar=s mar=rank8 mar=load mar=ram_write 


sp=qml 


sp=qup; ctrl=nop; 




fetch=fl; ctrl=load; 






rotf 


3cls : 








// MAR <= ++SP, MDR <= RAM (2 clocks); 








mar=s mar=rank8 mar=load mdr=ram_read 


sp=dpl ; 


ctrl=nop; 




// C <= rot8cl (A) (FL updated) 








c=b c=load fl=b fl=load alu=rot8cl alu 


=rank8u 


mdr=a mdr=rank8u mdr=bw; 




// MDR <= C 








mdr=a mdr=load c=a c=bw; 








// MAR <= — SP, RAM <= MDR (2 clocks) 








mar=s mar=rank8 mar=load mar=ram_write 


sp=qml 


sp=qup; ctrl=nop; 




fetch=fl; ctrl=load; 






rotf 


3crs : 








// MAR <= ++SP, MDR <= RAM (2 clocks) ; 








mar=s mar=rank8 mar=load mdr=ram_read 


sp=dpl ; 


ctrl=nop; 




// C <= rot8cr(A) (FL updated) 








c=b c=load fl=b fl=load alu=rot8cr alu 


=rank8u 


mdr=a mdr=rank8u mdr=bw; 




// MDR <= C 








mdr=a mdr=load c=a c=bw; 








// MAR <= — SP, RAM <= MDR (2 clocks) 








mar=s mar=rank8 mar=load mar=ram_write 


sp=qml 


sp=qup; ctrl=nop; 




fetch=fl; ctrl=load; 






rot! 


31s : 








// MAR <= ++SP, MDR <= RAM (2 clocks); 








mar=s mar=rank8 mar=load mdr=ram_read 


sp=dpl ; 


ctrl=nop; 




// C <= rot 81 (A) (FL updated) 








c=b c=load fl=b fl=load alu=rot81 alu= 


rank8u 


mdr=a mdr=rank8u mdr=bw; 




// MDR <= C 








mdr=a mdr=load c=a c=bw; 








// MAR <= — SP, RAM <= MDR (2 clocks) 








mar=s mar=rank8 mar=load mar=ram_write 


sp=qml 


sp=qup; ctrl=nop; 




fetch=fl; ctrl=load; 






rot! 


3rs : 







Version "E" 



835 



// MAR <= ++SP, MDR <= RAM (2 clocks); 




mar=s mar=rank8 mar=load mdr=ram_read sp=dpl; ctrl=nop; 




// C <= rot8r(A) (FL updated) 




c=b c=load fl=b fl=load alu=rot8r alu=rank8u mdr=a mdr=rank8u mdr=bw; 




// MDR <= C 




mdr=a mdr=load c=a c=bw; 




// MAR <= — SP, RAM <= MDR (2 clocks) 




mar=s mar=rank8 mar=load mar=ram_write sp=qml sp=qup; ctrl=nop; 




fetch=fl; ctrl=load; 




casts_uns : 




// MAR <= SP, MDR <= RAM (2 clocks) ; 




mar=s mar=rank8 mar=load mdr=ram_read; ctrl=nop; 




// C <= WD J? (FL updated) 




c=b c=load fl=b fl=load alu=a alu=rank8u mdr=a mdr=rankl6 mdr=bw; 




// MAR <= SP, RAM <= MDR (3 clocks) 




mar=s mar=rankl6 mar=load mar=ram_write ctrl=nop; ctrl=nop; 




fetch=fl; ctrl=load; 




casts_sig : 




// WAR <= SP, MDR <= RAM (2 clocks) ; 




mar=s mar=rank8 mar=load mdr=ram_read; ctrl=nop; 




// C <= WDJ? (FL updated) 




c=b c=load fl=b fl=load alu=a alu=rank8s mdr=a mdr=rankl6 mdr=bw; 




// MAR <= SP, RAM <= MDR (3 clocks) 




mar=s mar=rankl6 mar=load mar=ram_write ctrl=nop; ctrl=nop; 




fetch=fl; ctrl=load; 




call: 




// WAR <= PC+-2, MDR <= RAM (3 clocks) ; 




mar=p mar=rankl6 mar=load pc=dp2 mdr=ram_read; ctrl=nop; ctrl=nop; 




// TMP <= MDR 




tmp=a tmp=load mdr=a mdr=rankl6 mdr=bw; 




// MDR <= PC 




mdr=a mdr=load pc=a pc=bw; 




// WAR <= SP--2, RAM <= MDR (3 clocks) 




mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; Ctrl 


=nop; 


// PC <= TMP 




pc=a pc=load tmp=a tmp=bw; 




fetch=fl; ctrl=load; 




call_i : 




// WDR <= PC 




mdr=a mdr=load pc=a pc=bw; 




// WAR <= SP--2, RAM <= MDR (3 clocks) 




mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; Ctrl 


=nop; 


// PC <= I 





836 



Version "E" 



pc=a pc=load i=a i=bw; 
fetch=fl; ctrl=load; 
call_j : 

// MDR <= PC 

mdr=a mdr=load pc=a pc=bw; 

// MAR <= SP=-2, RAM <= MDR (3 clocks) 

mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; ctrl=nop; 
// PC <= J 

pc=a pc=load j=a j=bw; 
fetch=fl; ctrl=load; 
return : 

// MAR <= SP=+2, MDR <= RAM (3 clocks) ; 

mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; ctrl=nop; ctrl=nop; 
// SP <= MDR; 

fetch=fl sp=a sp=load mdr=a mdr=rankl6 mdr=bw; 
ctrl=load; 
ivtl : 

// MAR <= PC+-2, MDR <= RAM (3 clocks) ; 

mar=p mar=rankl6 mar=load pc=dp2 mdr=ram_read; ctrl=nop; ctrl=nop; 
// IVT <= MDR 

fetch=fl ivt=load mdr=a mdr=rankl6 mdr=bw; 
ctrl=load; 

int : 

// 

// push FL 

// 

// MDR <= FL 

mdr=a mdr=load fl=a fl=bw; 

// MAR <= SP--2, RAM <= MDR (3 clocks) 

mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; 
// 

// Reset interrupt enable flag (while the MEM module is working) . 

// 

fl=b fl=load alu=cleari; 
// 

// push (PC+1) to jump over the interrupt argument. 

// 

// MDR <= PC+1 

mdr=a mdr=load pc=a pc=qpl pc=bw; 

// MAR <= SP=-2, RAM <= MDR (3 clocks) 

mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; 
// 

// Convert the interrupt number from the argument, to the 



Version "E" 



837 



// interrupt vector table item address: 




// TMP <= IVT[int], int <= RAM[PC] 




// 




// MAR <= PC++, MDR <= RAM (2 clocks) ; 




mar=p mar=rankl6 mar=load pc=dpl mdr=ram_read; ctrl=nop; 




// TMP <= IVT[int] 




tmp=a tmp=load ivt=int_b ivt=bw mdr=b mdr=rank8u mdr=bw; 




// 




// Prepare to call the interrupt routine, loading the 




// interrupt vector table item address into PC. 




// 




// MAR <= TMP, MDR <= RAM (3 clocks); 




mar=t mar=rankl6 mar=load mdr=ram_read; ctrl=nop; ctrl=nop; 


// PC <= MDR; 




fetch=fl pc=a pc=load mdr=a mdr=rankl6 mdr=bw; 




ctrl=load; 




iret : 




// 




// Pop PC 




// 




// MAR <= SP=+2, MDR <= RAM (3 clocks); 




mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; ctrl=nop; 


ctrl=nop; 


// PC <= MDR; 




pc=a pc=load mdr=a mdr=rankl6 mdr=bw; 




// 




// Pop FL 




// 




// MAR <= SP-+2, MDR <= RAM (3 clocks) ; 




mar=s mar=rankl6 mar=load mdr=ram_read sp=dp2 ; ctrl=nop; 


ctrl=nop; 


// FL <= MDR; 




fetch=fl fl=a fl=load mdr=a mdr=rankl6 mdr=bw; 




ctrl=load; 




imrl : 




// MAR <= PC++, MDR <= RAM (2 clocks); 




mar=p mar=rank8 mar=load pc=dpl mdr=ram_read; ctrl=nop; 




// IRQ <= MDR; 




fetch=fl irq=mask_load mdr=a mdr=rank8u mdr=bw; 




ctrl=load; 




irq : 




// 




// push FL 




// 




// MDR <= FL 





838 



Version "E" 



mdr=a mdr=load fl=a fl=bw; 

// MAR <= SP=-2, RAM <= MDR (3 clocks) 

mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; 
// 

// Reset interrupt enable flag (while the MEM module is working) 

// 

fl=b fl=load alu=cleari; 
// 

// push (PC-1) to jump back to the opcode just read. 

// 

// MDR <= PC-1 

mdr=a mdr=load pc=a pc=qml pc=bw; 

// MAR <= SP=-2, RAM <= MDR (3 clocks) 

mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; 
// 

// Convert the interrupt number from the IRQ module, to the 
// interrupt vector table item address: 
// TMP <= IVT[int], int <= IRQ 

// 

// TMP <= IVT[INT[IRQ] ] 

tmp=a tmp=load ivt=int_a ivt=bw; 
// 

// Prepare to call the interrupt routine, loading the 
// interrupt vector table item address into PC. 

// 

// MAR <= TMP, MDR <= RAM (3 clocks); 

mar=t mar=rankl6 mar=load mdr=ram_read; ctrl=nop; ctrl=nop; 
// PC <= MDR; 

pc=a pc=load mdr=a mdr=rankl6 mdr=bw; 
// 

// Set the IRQ received as already done. 

// 
// 

fetch=fl irq=irq_done; 
ctrl=load; 
op_error : 
// 

// push FL 

// 

// MDR <= FL 

mdr=a mdr=load fl=a fl=bw; 

// MAR <= SP--2, RAM <= MDR (3 clocks) 

mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; ctrl=nop; 



Version "E" 



839 



// 




// Reset interrupt enable flag (while the MEM module is 


working) . 


// 




fl=b fl=load alu=cleari; 




// 




// push (PC-1) to jump back to the opcode just read. 




// 




// MDR <= PC-1 




mdr=a mdr=load pc=a pc=qml pc=bw; 




// MAR <= SP--2, RAM <= MDR (3 clocks) 




mar=s mar=rankl6 mar=load mar=ram_write sp=qm2 sp=qup; 


ctrl=nop; 


// 




// Convert the interrupt number 0 to the 




// interrupt vector table item address: 




// 




// TMP <= IVT[0] 




tmp=a tmp=load ivt=int_b ivt=bw bus=b bus=bw bus=0; 




// 




// Prepare to call the interrupt routine, loading the 




// interrupt vector table item address into PC. 




// 




// MAR <= TMP, MDR <= RAM (3 clocks); 




mar=t mar=rankl6 mar=load mdr=ram_read; ctrl=nop; ctrl= 


nop; 


// PC <= MDR; 




pc=a pc=load mdr=a mdr=rankl6 mdr=bw; 




fetch=f 1; 




ctrl=load; 




f lag_i_clr : 




// FL <= FL&OxFFEF 




fetch=fl fl=b fl=load alu=cleari; 




ctrl=load; 




f lag_i_set : 




// FL <= FL 10x0010 




fetch=fl fl=b fl=load alu=seti; 




ctrl=load; 




f lag_c_clr : 




// FL <= FL&OxFFFE 




fetch=fl fl=b fl=load alu=clearc; 




ctrl=load; 




f lag_c_set : 




// FL <= FL 10x0001 




fetch=fl fl=b fl=load alu=setc; 




ctrl=load; 





840 



Version "E" 



in. 


_num_a : 

// MAR <= PC++, MDR <= RAM (2 clocks) 










mar=p mar=rank8 mar=load pc=dpl mdr=ram_ 


read; 


Ctrl 


=nop; 




// IOA <= MDR 










1 O ^5 =^ 1 0^5 = 1 Hfld mHr^a mHr-ran]/ Pin mHr-hy 

_1_ OA. C-i _1_ v_y CJ- _1_ v_-* C-i 1 L L v^i _L_ CJ. ILL V^4. _L_ _L_ 1 1 J v W LJ. 1 L L v^4_ _L_ J^/ Vv / 










// I/O request (2 clocks) 










ioc=req; ctrl=nop; 










ctrl=nop; 




















// A <= IOC 










a=a a=load ioc=bw; 










ctrl=nop; 










/~* ~\~ v 1 — n i^t^ ■ 
LI X — I lUj-> ^ 










fetch=f 1; 










ctrl=load; 








in. 


_num_b : 

// MAR <= PC++, MDR <= RAM (2 clocks) 










mar=p mar=rank8 mar=load pc=dp2 mdr=ram_ 


read; 


Ctrl 


=nop; 




// IOA <= MDR 










ioa=a ioa=load mdr=a mdr=rank8u mdr=bw; 










// I/O request (2 clocks) 










ioc=req; ctrl=nop; 










// B <= IOC 










fetch=fl b=a b=load ioc=bw; 










ctrl=load; 








in. 


_num_mi : 

// MAR <= PC++, MDR <= RAM (2 clocks) 










mar=p mar=rank8 mar=load pc=dp2 mdr=ram_ 


read; 


Ctrl 


=nop; 




// IOA <= MDR 










ioa=a ioa=load mdr=a mdr=rank8u mdr=bw; 










// I/O request (2 clocks) 










ioc=req; ctrl=nop; 










// MDR <= IOC 










mdr=a mdr=load ioc=bw; 










// WAR <= I, RAM <= MDR (3 clocks) 










mar=i mar=rank!6 mar=load mar=ram_write; 


Ctrl 


=nop; 


ctrl=nop; 




fetch=fl; ctrl=load; 









Version "E" 



841 





num_mj : 

// MAR <= PC++, MDR <= RAM (2 clocks) 










mar=p mar=rank8 mar=load pc=dp2 mdr=ram_ 


read; 


Ctrl 


=nop; 




// IOA <= MDR 










ioa=a ioa=load mdr=a mdr=rank8u mdr=bw; 










// I/O request (2 clocks) 










ioc=req; ctrl=nop; 










// MDR <= IOC 










mdr=a mdr=load ioc=bw; 










// MAR <= J, RAM <= MDR (3 clocks) 










mar=j mar=rankl6 mar=load mar=ram_write; 


Ctrl 


=nop; 


ctrl=nop; 




fetch=fl; ctrl=load; 








out 


_a_num : 

// MAR <= PC++, MDR <= RAM (2 clocks) 










mar=p mar=rank8 mar=load pc=dpl mdr=ram_ 


read; 


Ctrl 


=nop; 




// IOA <= MDR 










ioa=a ioa=load mdr=a mdr=rank8u mdr=bw; 










// IOC <= A 










ioc=load a=a a=bw; 










// I/O request 










ioc=req 










fetch=fl; ctrl=load; 








out 


_b_num : 

// MAR <= PC++, MDR <= RAM (2 clocks) 










mar=p mar=rank8 mar=load pc=dpl mdr=ram_ 


read; 


Ctrl 


=nop; 




// IOA <= MDR 










ioa=a ioa=load mdr=a mdr=rank8u mdr=bw; 










// IOC <= B 










ioc=load b=a b=bw; 










// I/O request 










ioc=req 










fetch=fl; ctrl=load; 








out 


_mi_num : 

// MAR <= PC++, MDR <= RAM (2 clocks) 










mar=p mar=rank8 mar=load pc=dpl mdr=ram_ 


read; 


Ctrl 


=nop; 




// IOA <= MDR 










ioa=a ioa=load mdr=a mdr=rank8u mdr=bw; 










// MAR <= I, MDR <= RAM (3 clocks) ; 










mar=i mar=rankl6 mar=load mdr=ram_read; 


ctrl= 


nop; 


ctrl=nop; 




// IOC <= MDR; 










ioc=req 










fetch=fl; ctrl=load; 








out 


_m j_num : 









842 



Version "E" 



// MAR <= PC++, MDR <= RAM (2 clocks) 

mar=p mar=rank8 mar=load pc=dpl mdr=ram_read; ctrl=nop; 
// IOA <= MDR 

ioa=a ioa=load mdr=a mdr=rank8u mdr=bw; 
// MAR <= J, MDR <= RAM (3 clocks); 

mar=j mar=rankl6 mar=load mdr=ram_read; ctrl=nop; ctrl=nop; 
// IOC <= MDR; 

ioc=req 

fetch=fl; ctrl=load; 
if ack_jump : 

// MAR <= PC++, MDR <= RAM (2 clocks) 

mar=p mar=rank8 mar=load pc=dpl mdr=ram_read; ctrl=nop; 
// IOA <= MDR 

ioa=a ioa=load mdr=a mdr=rank8u mdr=bw; 

// C <= alu ( I/O Isack) (FL updated) and conditional jump. 

c=b c=load fl=b fl=load alu=a alu=rank8s ioc=isack ioc=bw 
addr=jump jump=zero_f; 

// discard destination address: ++PC and fetch 

pc=qp2 pc=qup fetch=fl; 
ctrl=load; 
if ack_call : 

// MAR <= PC++, MDR <= RAM (2 clocks) 

mar=p mar=rank8 mar=load pc=dpl mdr=ram_read; ctrl=nop; 
// IOA <= MDR 

ioa=a ioa=load mdr=a mdr=rank8u mdr=bw; 

// C <= alu (I/O isack) (FL updated) and conditional jump. 

c=b c=load fl=b fl=load alu=a alu=rank8s ioc=isack ioc=bw 
addr=call jump=zero_f; 

// discard destination address: ++PC and fetch 

pc=qp2 pc=qup fetch=fl; 
ctrl=load; 
cmpr : 

// FL(A-B) 

fetch=fl fl=b fl=load alu=sub alu=rankl6; 
ctrl=load; 
testr : 

// FL (A&B) , MPC <= # fetch 

fetch=fl fl=b fl=load alu=and alu=rankl6; 
ctrl=load; 
cmpi : 

// MAR <= I, MDR <= RAM (3 clocks) ; 

mar=i mar=rank!6 mar=load mdr=ram_read; ctrl=nop; ctrl=nop; 
// A <= MDR; 



Version "E" 



843 



a=a a=load mdr=a mdr=rankl6 mdr=bw; 










// MAR <= J, MDR <= RAM (3 clocks); 










mar=j mar=rankl6 mar=load mdr=ram_read; 


ctrl=nop; 


ctrl = 


nop; 




// B <= MDR; 










b=a b=load mdr=a mdr=rankl6 mdr=bw 










addr=cmpr jump=true; 










testi : 










// MAR <= I, MDR <= RAM (3 clocks) ; 










mar=i mar=rankl6 mar=load mdr=ram_read; 


ctrl=nop; 


ctrl = 


nop; 




// A <= MDR; 










a=a a=load mdr=a mdr=rankl6 mdr=bw; 










// MAR <= J, MDR <= RAM (3 clocks); 










mar=j mar=rankl6 mar=load mdr=ram_read; 


ctrl=nop; 


ctrl = 


nop; 




// B <= MDR; 










b=a b=load mdr=a mdr=rankl6 mdr=bw 










addr=testr jump=true; 










cmps : 










// MAR <= SP, MDR <= RAM (3 clocks) ; 










mar=s mar=rankl6 mar=load mdr=ram_read; 


ctrl=nop; 


ctrl = 


nop; 




// B <= MDR; 










b=a b=load mdr=a mdr=rankl6 mdr=bw; 










// MAR <= SP+2, MDR <= RAM (3 clocks); 










mar=s mar=rankl6 mar=load mdr=ram_read 


sp=qp2 ; ctrl=nop 


; Ctrl 


=nop; 


// A <= MDR; 










a=a a=load mdr=a mdr=rankl6 mdr=bw 










addr=cmpr jump=true; 










tests : 










// WAR <= SP, MDR <= RAM (3 clocks) ; 










mar=s mar=rankl6 mar=load mdr=ram_read; 


ctrl=nop; 


ctrl= 


nop; 




// B <= MDR; 










b=a b=load mdr=a mdr=rankl6 mdr=bw; 










// MAR <= SP+2, MDR <= RAM (3 clocks) ; 










mar=s mar=rankl6 mar=load mdr=ram_read 


sp=qp2 ; ctrl=nop 


; Ctrl 


=nop; 


// A <= MDR; 










a=a a=load mdr=a mdr=rankl6 mdr=bw 










addr=testr jump=true; 










cmp8i : 










// MAR <= I, MDR <= RAM (2 clocks); 










mar=i mar=rank8 mar=load mdr=ram_read; 


ctrl=nop; 








// A <= MDR; 










a=a a=load mdr=a mdr=rank8s mdr=bw; 










// MAR <= J, MDR <= RAM (2 clocks) ; 










mar=j mar=rank8 mar=load mdr=ram_read; 


ctrl=nop; 









844 



Version "E" 



// B <= MDR; 








b=a b=load mdr=a mdr=rank8s mdr=bw; 








addr=cmpr jump=true; 








test8i : 








// MAR <= I, MDR <= RAM (2 clocks) ; 








mar=i mar=rank8 mar=load mdr=ram_read; 


ctrl=nop; 






// A <= MDR; 








a=a a=load mdr=a mdr=rank8s mdr=bw; 








// MAR <= J, MDR <= RAM (2 clocks) ; 








mar=j mar=rank8 mar=load mdr=ram_read; 


ctrl=nop; 






// B <= MDR; 








b=a b=load mdr=a mdr=rank8s mdr=bw; 








addr=and jump=true; 








cmp8s : 








// WAR <= SP, MDR <= RAM (3 clocks) ; 








mar=s mar=rank8 mar=load mdr=ram_read; 


ctrl=nop; ctrl= 


nop; 




// B <= MDR; 








b=a b=load mdr=a mdr=rank8s mdr=bw; 








// MAR <= SP+1, MDR <= RAM (3 clocks); 








mar=s mar=rank8 mar=load mdr=ram_read 


sp=qpl; ctrl=nop 


; Ctrl 


=nop; 


// A <= MDR; 








a=a a=load mdr=a mdr=rank8s mdr=bw 








addr=cmpr jump=true; 








test8s : 








// WAR <= SP, MDR <= RAM (3 clocks) ; 








mar=s mar=rank8 mar=load mdr=ram_read; 


ctrl=nop; ctrl= 


nop; 




// B <= MDR; 








b=a b=load mdr=a mdr=rank8s mdr=bw; 








// WAR <= SP+1, MDR <= RAM (3 clocks); 








mar=s mar=rank8 mar=load mdr=ram_read 


sp=qpl; ctrl=nop 


; Ctrl 


=nop; 


// A <= MDR; 








a=a a=load mdr=a mdr=rank8s mdr=bw 








addr=testr jump=true; 








// 








stop : 








ctrl=stop; 








// 








end 









Version "E 



845 



12.15 Macrocode 



« 



As an example, the following listing shows a simple program that reads from the 
keyboard and prints the same text on the virtual screen. The keyboard input is read 
after a hardware interrupt. 

Listing 12.44. Macrocode example for TKGate. 

begin macrocode @ 0 



. short 


0x0025 


// 


CPU opcode error 


. short 


0x0024 


// 


CPU 


. short 


0x0024 


// 


CPU 


. short 


0x0024 


// 


CPU 


. short 


0x0024 


// 


IRQ rtc 


. short 


0x0026 


// 


IRQ keyboard 


. short 


0x0024 


// 


IRQ hard disk 


. short 


0x0024 


// 


IRQ 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 


. short 


0x0024 


// 


software 



clef ault_interrupt_rout ine : 

iret 
op_code_error : 

stop 
keyboard : 



jump # start 
nop 

interrupt_vect or_t able 



in 1,%A 
equal 

jump %zero, 1 , #keyboard_end 

out %A, 0 

jump #keyboard 



// keyboard read 
// update flags 
// if zero exit 



// print on screen 
// continue 



keyboard_end : 



846 



Version "E" 





iret 








start : 












Cp UXUUoU, -51 






SeC SZ.2LCK OOZ.Z.OIU 




Cp -o 1 , -o or 










// 










lvti f interrupt vecior_ 


_L dDie 








/ / 
// 










-i TYl ir~ 1 M w M XT' 






an irty accepveo. 




flag_i 1 




// 


Xi<y enabled 


// 










keyboard_reset : 










in 1,%A 




// 


keyboard read . 




equal 




// 


upaatc i layo 




jump %zero, 0 , #keyboard_ 


.reset 


// 


if not zero continue 


// 










loop : 


jump #loop 








stop : 


// never 


reach 


the end. 




stop 








end 











Chapter I O 

Version VV F": 32-bit registers, big-endian, privileges 

« 





13.1 


General purpose modules 


850 




13.2 


Addition modules 


853 




13.3 


Multiple clock lines 


857 




13.4 


Bus 


860 


bera.net 


13.5 


Registers: simple and with post-increment 


862 


aticali 


13.6 


Memory segmentation 


863 


nform 


13.7 


Module "DA" 


864 


£ 


13.8 


Module "CA" 


865 


13.9 


Modules "M" and "RAM" 


866 


u 
£ 


13.10 


Module "IR" 


871 


© 


13.11 


Module "MD" 


873 


S 
s 
a. 
ft, 


13.12 


Module "IRQ" 


875 


uele Giacomini — i 


13.13 


Module "IVT" 


877 


13.14 


Module "ALU" 


878 


13.15 


Module "FL" 


887 


©Dat 


13.16 


Module "TTY" 


890 


►e 

~r~. 


13.17 


Module "HDD" 


894 


f 


13.18 


Module "CTRL" 


899 


5 


13.19 


Memory and microcode fields 


902 


ift-20] 


13.20 


Opcodes 


904 


"3 

"ft, 


13.21 


Data initialization 


934 


n punc 


13.22 


Microcode 


935 


& 


13.23 


Process mode and interrupts 


966 


1 


13.24 


Macrocode example: 'memcpy' 


967 



848 Version "F": 32-bit registers, big-endian, privileges 

13.25 Macrocode example: TTY with interrupt 969 

13.26 Macrocode example: user and supervisor 972 



This version of the CPU is made with 32-bit registers and is able to distinguish be- 
tween privileged and unprivileged processes: unprivileged processes cannot access 
directly the I/O devices and cannot modify some status flags. The opcode remains 
limited to 8 -bit width, including the argument represented by registers: because of 
this limitation, there are few macrocode instructions, but enough for the demonstra- 
tion purpose of the project. 



Attachments 


Description 


attachments/xcpu/xcpu-f. v 


TKGate Verilog netlist source file. 


attachments/xcpu/xcpu-f-memcpy.gm 
attachments/xcpu/xcpu-f-tty-simple.gm 
attachments/xcpu/xcpu-f-user-process. 
gm 

attachments/xcpu/xcpu-f-supervisor-and- 
user.gm 


TKGate microcode and macrocode alter- 
native source files. 


attachments/xcpu/xcpu-f-terminal. vpd. tcl 


TCL/Tk script related to the terminal mod- 
ule TTY. 



Version "F": 32-bit registers, big-endian, privileges 



849 



Figure 13.2. Simple CPU, version "F". 




850 



Version "F": 32-bit registers, big-endian, privileges 



« 



13.1 General purpose modules 

The following figures show some general purpose modules. Some of them already 
appeared in previous versions of the project, with or without modifications. 

Figure 13.3. Module RANK32 and submodules: rank reduction and sign extention. 



32 



f RANK32 



32 



2 



Y>" 



/ 32 



RANK32 



RPL8 



15 



sign 



<f 



RNK32 



□ 



Y>" 



X 

V 



0 1 



X 
V 



RNK32 



i 4- 



X Y 

f RPL8 



4- 4- 



X Y 

RPL8 



X Y 

RPL8 



4- 4- 



X Y 

, RPL8 



~j8 



Version "F": 32-bit registers, big-endian, privileges 



851 



Figure 13.4. Modules Dn. 



Ck> 



C > 



module Dl 
(Dflip-flop) 




/ 2 

V 
Q 



: 




\ 


/ 






/ 





p 

V 



module D2 



i 




P 


Q 


D 




D1 


Q 


- Ck 




C 



A 
c 



Q P D 
D1 

Q g Ck 



-<Ck 



P 

V 





P 




Q 


D 

D2 


Q 


c 


Ck 



A 
c 



module D4 



■Q P D 
D2 

■Q ^ Ck 



-<Ck 



/ 4 

V 



852 



Version "F": 32-bit registers, big-endian, privileges 



Figure 13.5. Modules dhw. 



module E (enable) 



p >- 
s>- 

E>- 
R>- 

C >- 



> 



> 



> 



D 

V 



module DH1 

p >- 




> Q 



^ Q 



P > 



C > 



H > 



D 

V 



/2 



I 1 

1- o 



module DH2 



p > 



c >- 



H >" 



D H 




DH1 Q 


H C 





D 

V 



/A 



/ 



D P 




DH2 Q 


H C 






/2 



module DH4 



Q 




Q 



Version "F": 32-bit registers, big-endian, privileges 



853 



Figure 13.6. Modules Fn. A module Fn, provided that the input Ti is asserted, 
returns the count of the impulses received at the Ck input. 

77 „ r„ 



p 

V 



Q < 




<T 



To 











P 




Q 




Ti 


To 


F1 


Ck 






c 





A 
C 



— o 



Q 

A 



p 

V 




Fl 

-<Ti 

<Ck 



A 
C 



P 

V 



F2 



Q Ti 
F1 

To Ck 
C 
It 



-<Ti 



-<Ck 




<Ck 



13.2 Addition modules 

This version of the simple CPU works with 32-bit registers and ALU. The ALU, some 
registers and some other modules contain an addition module for various reasons. For 
example DA and CA need to calculate the real memory address and some registers 
need to be incremented or decremented. To ensure that the additions are made as fast 
as possible, the technique of the carry lookahead is used. 



« 



854 Version "F": 32-bit registers, big-endian, privileges 

Figure 13.7. Module SUM8: 8-bit addition with carry lookahead. 






Version "F": 32-bit registers, big-endian, privileges 



855 



Figure 13.8. Module CLH4 (carry lookahead). 



GO PO CO 

V V v 



G1 P1 

V V 



G2 P2 

V V 



G3 P3 

V V 



o-r> 



o- 



l L 



> 



D- 



> C1 



> C2 



> C3 



C4 



-^ P4 = P3*P2*P1*P0 



> 



-> G4 = G3+ 

P3*G2+ 
P3*P2*G1 + 
P3*P2*P1*G0 





t t 


+ 


k k k 


k k 


k 


k k 


C4 
P4 
G4 


G3 P3 


C3 


G2 P2 C2 
CLH4 


G1 P1 


C1 


GO PO 

CO 



856 



Version "F": 32-bit registers, big-endian, privileges 



Figure 13.9. Module SUM32. 





7^32 ^32 




A B 


*■ 


CoO 


♦ 

4 


Co1 SUM32 Ci 


4 


Co 


-6 




v S 



CoO < 
Co1 <- 



v <- 



Co -S- 



4 

■y=- 



3_ 
4 2 

^ T 

0 



A 


B 


C7 S ^ 8 


CO 


C8 




G8 P8 


S 



A 


B 


C7 sV ytJV& 


CO 


C8 




G8 P8 


S 



A 


B 




CO 


C8 




G8 P8 


S 



B 

V 



/ 32 



A 


B 




CO 


C8 




G8 P8 


S 



C2 

CLH4 



CO 



-<Ci 



7:0 



15:8 
23:16 
31:24 



S 



Figure 13.10. Module sum32: it is just a wrapper around the module SUM32. 



32 





A B 




<- 


Co sum32 ci 


4- 




s 






4*32 





CO 



A 

V 

/^32 



-4r 



B 

V 

/^32 



A 


B 


CoO 




Co1 


SUM32 Ci 


Co 




V 


S 



/ 

/ 

V 



32 



<Ci 



Version "F": 32-bit registers, big-endian, privileges 



857 



13.3 Multiple clock lines 

All the previous versions of the simple CPU suffer from clock timing problems that 
sometimes arise with the memory access. With this version there is a clock generating 
seven pulses at different offsets: with this method, up to fourteen edge triggers can be 
selected. 

Figure 13.11. Seven clock signals. 







r> 




o 


r> 


o 


? — 1 
Q 


o 


? — * 
o 


o 


? — i 
© 
















R- 


R- 


R- 


R- 


R- 




bo 











Y Y Y Y Y Y Y 

| clock 0 

clock 1 

I I clock 2 

I | clock 3 

| | clock 4 

I | clock 5 

| clock 6 

A A A A A A A 



tN °n > ^ *0 



«Vi »!g »1£ «b£ 

Q 0> Q 0> Q <5 



The clock pulse is produced by the module CLKCLR, described by the following fig- 
ures. 



858 



Version "F": 32-bit registers, big-endian, privileges 



Figure 13.12. Module clkclr. 



Oi 



to DLY t1 



n 



'4 
DLY 



to DLY t1 



to DLY t1* 



-i 7^ 



to DLY t1 



to DLY t1 



to DLY t1 



1—4 



to DLY t1 



Q r T 
T1 

Q r Ok 



DLY 



CLKCLR 
Rst Clr 



7 

Ck 



o 



As it is for the previous version of the simple CPU, the clock generator is started 
by a single shot (the module one_up), represented on the left of the figure by a red 
'stair'. Then the modules DLY are simple delay lines, made of non-inverting buffers. 
To tune the frequency, the delay lines can be adapted with the input value DLY: zero 
represents the maximum frequency (the shortest delay), 15 produces the minimum 
frequency (the longest delay). As for the previous clock versions, the clear line (Clr 
output) is to be coordinated with the clock. 



Version "F": 32-bit registers, big-endian, privileges 859 
Listing 13.13. Module one_up, used to start